diff --git a/build/Build.cs b/build/Build.cs index 43dc4947..fc83e858 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -443,7 +443,7 @@ protected override void OnBuildInitialized() AppveyorArtifacts.ForEach((artifact) => { - Process proc = new Process(); + var proc = new Process(); proc.StartInfo = new ProcessStartInfo("appveyor", $"PushArtifact \"{artifact}\""); if (!proc.Start()) { @@ -464,7 +464,7 @@ protected override void OnBuildInitialized() { AbsolutePath logExpertApplicationData = SpecialFolder(SpecialFolders.ApplicationData) / "LogExpert"; - DirectoryInfo info = new DirectoryInfo(logExpertApplicationData); + var info = new DirectoryInfo(logExpertApplicationData); info.GetDirectories().ForEach(a => a.Delete(true)); logExpertApplicationData.DeleteDirectory(); }); @@ -474,7 +474,7 @@ protected override void OnBuildInitialized() { AbsolutePath logExpertDocuments = SpecialFolder(SpecialFolders.UserProfile) / "Documents" / "LogExpert"; - DirectoryInfo info = new DirectoryInfo(logExpertDocuments); + var info = new DirectoryInfo(logExpertDocuments); info.GetDirectories().ForEach(a => a.Delete(true)); logExpertDocuments.DeleteDirectory(); }); diff --git a/src/.editorconfig b/src/.editorconfig index 7225b5c0..17f73e3d 100644 --- a/src/.editorconfig +++ b/src/.editorconfig @@ -555,7 +555,7 @@ dotnet_code_quality.CA1001.excluded_symbol_names = dotnet_code_quality.CA1001.excluded_type_names_with_derived_types = # CA1002: Do not expose generic lists -dotnet_diagnostic.CA1002.severity = warning +dotnet_diagnostic.CA1002.severity = suggestion dotnet_code_quality.CA1002.api_surface = all # CA1003: Use generic event handler instances @@ -906,7 +906,7 @@ dotnet_code_quality.CA1806.additional_use_results_methods = dotnet_diagnostic.CA1810.severity = warning # CA1812: Avoid uninstantiated internal classes -dotnet_diagnostic.CA1812.severity = warning +dotnet_diagnostic.CA1812.severity = None # CA1813: Avoid unsealed attributes dotnet_diagnostic.CA1813.severity = suggestion @@ -1021,7 +1021,7 @@ dotnet_diagnostic.CA1849.severity = warning dotnet_diagnostic.CA1850.severity = warning # CA2000: Dispose objects before losing scope -dotnet_diagnostic.CA2000.severity = warning +dotnet_diagnostic.CA2000.severity = None dotnet_code_quality.CA2000.excluded_symbol_names = dotnet_code_quality.CA2000.excluded_type_names_with_derived_types = dotnet_code_quality.CA2000.dispose_analysis_kind = NonExceptionPaths @@ -1100,7 +1100,7 @@ dotnet_code_quality.CA2208.api_surface = all dotnet_diagnostic.CA2211.severity = warning # CA2213: Disposable fields should be disposed -dotnet_diagnostic.CA2213.severity = warning +dotnet_diagnostic.CA2213.severity = None # CA2214: Do not call overridable methods in constructors dotnet_diagnostic.CA2214.severity = warning diff --git a/src/AutoColumnizer/AutoColumnizer.cs b/src/AutoColumnizer/AutoColumnizer.cs index c699274c..bed59327 100644 --- a/src/AutoColumnizer/AutoColumnizer.cs +++ b/src/AutoColumnizer/AutoColumnizer.cs @@ -2,64 +2,63 @@ using System; -namespace AutoColumnizer -{ - public class AutoColumnizer : ILogLineColumnizer - { - #region ILogLineColumnizer implementation +namespace AutoColumnizer; - public string Text => GetName(); +public class AutoColumnizer : ILogLineColumnizer +{ + #region ILogLineColumnizer implementation - public bool IsTimeshiftImplemented() - { - return true; - } + public string Text => GetName(); - public string GetName() - { - return "Auto Columnizer"; - } + public bool IsTimeshiftImplemented() + { + return true; + } - public string GetDescription() - { - return "Automatically find the right columnizer for any file"; - } + public string GetName() + { + return "Auto Columnizer"; + } + public string GetDescription() + { + return "Automatically find the right columnizer for any file"; + } - public int GetColumnCount() - { - throw new NotImplementedException(); - } - public string[] GetColumnNames() - { - throw new NotImplementedException(); - } + public int GetColumnCount() + { + throw new NotImplementedException(); + } - public IColumnizedLogLine SplitLine(ILogLineColumnizerCallback callback, ILogLine line) - { - throw new NotImplementedException(); - } + public string[] GetColumnNames() + { + throw new NotImplementedException(); + } - public void SetTimeOffset(int msecOffset) - { - throw new NotImplementedException(); - } + public IColumnizedLogLine SplitLine(ILogLineColumnizerCallback callback, ILogLine line) + { + throw new NotImplementedException(); + } - public int GetTimeOffset() - { - throw new NotImplementedException(); - } + public void SetTimeOffset(int msecOffset) + { + throw new NotImplementedException(); + } - public DateTime GetTimestamp(ILogLineColumnizerCallback callback, ILogLine line) - { - throw new NotImplementedException(); - } + public int GetTimeOffset() + { + throw new NotImplementedException(); + } - public void PushValue(ILogLineColumnizerCallback callback, int column, string value, string oldValue) - { - } + public DateTime GetTimestamp(ILogLineColumnizerCallback callback, ILogLine line) + { + throw new NotImplementedException(); + } - #endregion ILogLineColumnizer implementation + public void PushValue(ILogLineColumnizerCallback callback, int column, string value, string oldValue) + { } + + #endregion ILogLineColumnizer implementation } \ No newline at end of file diff --git a/src/ColumnizerLib.UnitTests/ColumnTests.cs b/src/ColumnizerLib.UnitTests/ColumnTests.cs index e61e57c5..649b132a 100644 --- a/src/ColumnizerLib.UnitTests/ColumnTests.cs +++ b/src/ColumnizerLib.UnitTests/ColumnTests.cs @@ -3,83 +3,82 @@ using System; using System.Text; -namespace ColumnizerLib.UnitTests +namespace ColumnizerLib.UnitTests; + +[TestFixture] +public class ColumnTests { - [TestFixture] - public class ColumnTests + [Test] + public void Column_LineCutOf() { - [Test] - public void Column_LineCutOf() + Column column = new(); + + StringBuilder builder = new(); + + for (var i = 0; i < 4675; i++) { - Column column = new(); + builder.Append("6"); + } - StringBuilder builder = new(); + var expected = builder + "..."; + builder.Append("1234"); - for (int i = 0; i < 4675; i++) - { - builder.Append("6"); - } + column.FullValue = builder.ToString(); - string expected = builder + "..."; - builder.Append("1234"); + Assert.That(column.DisplayValue, Is.EqualTo(expected)); + Assert.That(column.FullValue, Is.EqualTo(builder.ToString())); + } - column.FullValue = builder.ToString(); + [Test] + public void Column_NoLineCutOf() + { + Column column = new(); - Assert.That(column.DisplayValue, Is.EqualTo(expected)); - Assert.That(column.FullValue, Is.EqualTo(builder.ToString())); - } + StringBuilder builder = new(); - [Test] - public void Column_NoLineCutOf() + for (var i = 0; i < 4675; i++) { - Column column = new(); + builder.Append("6"); + } + + var expected = builder.ToString(); - StringBuilder builder = new(); + column.FullValue = expected; - for (int i = 0; i < 4675; i++) - { - builder.Append("6"); - } + Assert.That(column.DisplayValue, Is.EqualTo(expected)); + Assert.That(column.FullValue, Is.EqualTo(expected)); + } - string expected = builder.ToString(); + [Test] + public void Column_NullCharReplacement() + { + Column column = new(); - column.FullValue = expected; + column.FullValue = "asdf\0"; - Assert.That(column.DisplayValue, Is.EqualTo(expected)); - Assert.That(column.FullValue, Is.EqualTo(expected)); + //Switch between the different implementation for the windows versions + //Not that great solution but currently I'm out of ideas, I know that currently + //only one implementation depending on the windows version is executed + if (Environment.Version >= Version.Parse("6.2")) + { + Assert.That(column.DisplayValue, Is.EqualTo("asdf␀")); } - - [Test] - public void Column_NullCharReplacement() + else { - Column column = new(); - - column.FullValue = "asdf\0"; - - //Switch between the different implementation for the windows versions - //Not that great solution but currently I'm out of ideas, I know that currently - //only one implementation depending on the windows version is executed - if (Environment.Version >= Version.Parse("6.2")) - { - Assert.That(column.DisplayValue, Is.EqualTo("asdf␀")); - } - else - { - Assert.That(column.DisplayValue, Is.EqualTo("asdf ")); - } - - Assert.That(column.FullValue, Is.EqualTo("asdf\0")); + Assert.That(column.DisplayValue, Is.EqualTo("asdf ")); } - [Test] - public void Column_TabReplacement() - { - Column column = new(); + Assert.That(column.FullValue, Is.EqualTo("asdf\0")); + } + + [Test] + public void Column_TabReplacement() + { + Column column = new(); - column.FullValue = "asdf\t"; + column.FullValue = "asdf\t"; - Assert.That(column.DisplayValue, Is.EqualTo("asdf ")); - Assert.That(column.FullValue, Is.EqualTo("asdf\t")); - } + Assert.That(column.DisplayValue, Is.EqualTo("asdf ")); + Assert.That(column.FullValue, Is.EqualTo("asdf\t")); } } \ No newline at end of file diff --git a/src/ColumnizerLib.UnitTests/Extensions/LogLineExtensionsTests.cs b/src/ColumnizerLib.UnitTests/Extensions/LogLineExtensionsTests.cs index 47ace2eb..c6746b62 100644 --- a/src/ColumnizerLib.UnitTests/Extensions/LogLineExtensionsTests.cs +++ b/src/ColumnizerLib.UnitTests/Extensions/LogLineExtensionsTests.cs @@ -3,31 +3,30 @@ using NUnit.Framework; -namespace ColumnizerLib.UnitTests.Extensions -{ - [TestFixture] +namespace ColumnizerLib.UnitTests.Extensions; + +[TestFixture] - internal class LogLineExtensionsTests +internal class LogLineExtensionsTests +{ + private class TestingLogLine : ILogLine { - private class TestingLogLine : ILogLine - { - public string FullLine { get; set; } + public string FullLine { get; set; } - public int LineNumber { get; set; } + public int LineNumber { get; set; } - public string Text { get; set; } - } + public string Text { get; set; } + } - [Test] - public void ToClipBoardText_ReturnsExpected() + [Test] + public void ToClipBoardText_ReturnsExpected() + { + var underTest = new TestingLogLine { - var underTest = new TestingLogLine - { - FullLine = "a fullLine", - LineNumber = 89, - Text = "a text" - }; - Assert.That(underTest.ToClipBoardText(), Is.EqualTo("\t90\ta fullLine")); - } + FullLine = "a fullLine", + LineNumber = 89, + Text = "a text" + }; + Assert.That(underTest.ToClipBoardText(), Is.EqualTo("\t90\ta fullLine")); } } diff --git a/src/ColumnizerLib/Column.cs b/src/ColumnizerLib/Column.cs index ff5bf308..03fb37b6 100644 --- a/src/ColumnizerLib/Column.cs +++ b/src/ColumnizerLib/Column.cs @@ -1,117 +1,116 @@ using System; using System.Collections.Generic; -namespace LogExpert +namespace LogExpert; + +public class Column : IColumn { - public class Column : IColumn - { - #region Fields + #region Fields - private static readonly int _maxLength = 4678 - 3; - private static readonly string _replacement = "..."; + private static readonly int _maxLength = 4678 - 3; + private static readonly string _replacement = "..."; - private static readonly IEnumerable> _replacements; + private static readonly IEnumerable> _replacements; - private string _fullValue; + private string _fullValue; - #endregion + #endregion - #region cTor + #region cTor - static Column() - { - List> replacements = new List>( - new Func[] - { - //replace tab with 3 spaces, from old coding. Needed??? - input => input.Replace("\t", " "), + static Column() + { + var replacements = new List>( + new Func[] + { + //replace tab with 3 spaces, from old coding. Needed??? + input => input.Replace("\t", " "), - //shorten string if it exceeds maxLength - input => + //shorten string if it exceeds maxLength + input => + { + if (input.Length > _maxLength) { - if (input.Length > _maxLength) - { - return input.Substring(0, _maxLength) + _replacement; - } - - return input; + return input.Substring(0, _maxLength) + _replacement; } - }); - - if (Environment.Version >= Version.Parse("6.2")) - { - //Win8 or newer support full UTF8 chars with the preinstalled fonts. - //Replace null char with UTF8 Symbol U+2400 (␀) - replacements.Add(input => input.Replace("\0", "␀")); - } - else - { - //Everything below Win8 the installed fonts seems to not to support reliabel - //Replace null char with space - replacements.Add(input => input.Replace("\0", " ")); - } - _replacements = replacements; + return input; + } + }); - EmptyColumn = new Column {FullValue = string.Empty}; + if (Environment.Version >= Version.Parse("6.2")) + { + //Win8 or newer support full UTF8 chars with the preinstalled fonts. + //Replace null char with UTF8 Symbol U+2400 (␀) + replacements.Add(input => input.Replace("\0", "␀")); + } + else + { + //Everything below Win8 the installed fonts seems to not to support reliabel + //Replace null char with space + replacements.Add(input => input.Replace("\0", " ")); } - #endregion + _replacements = replacements; - #region Properties + EmptyColumn = new Column {FullValue = string.Empty}; + } - public static IColumn EmptyColumn { get; } + #endregion - public IColumnizedLogLine Parent { get; set; } + #region Properties - public string FullValue - { - get => _fullValue; - set - { - _fullValue = value; + public static IColumn EmptyColumn { get; } - string temp = FullValue; + public IColumnizedLogLine Parent { get; set; } - foreach (var replacement in _replacements) - { - temp = replacement(temp); - } + public string FullValue + { + get => _fullValue; + set + { + _fullValue = value; - DisplayValue = temp; - } - } + var temp = FullValue; - public string DisplayValue { get; private set; } + foreach (var replacement in _replacements) + { + temp = replacement(temp); + } - string ITextValue.Text => DisplayValue; + DisplayValue = temp; + } + } - #endregion + public string DisplayValue { get; private set; } - #region Public methods + string ITextValue.Text => DisplayValue; - public static Column[] CreateColumns(int count, IColumnizedLogLine parent) - { - return CreateColumns(count, parent, string.Empty); - } + #endregion - public static Column[] CreateColumns(int count, IColumnizedLogLine parent, string defaultValue) - { - Column[] output = new Column[count]; + #region Public methods - for (int i = 0; i < count; i++) - { - output[i] = new Column {FullValue = defaultValue, Parent = parent}; - } + public static Column[] CreateColumns(int count, IColumnizedLogLine parent) + { + return CreateColumns(count, parent, string.Empty); + } - return output; - } + public static Column[] CreateColumns(int count, IColumnizedLogLine parent, string defaultValue) + { + var output = new Column[count]; - public override string ToString() + for (var i = 0; i < count; i++) { - return DisplayValue ?? string.Empty; + output[i] = new Column {FullValue = defaultValue, Parent = parent}; } - #endregion + return output; } + + public override string ToString() + { + return DisplayValue ?? string.Empty; + } + + #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/ColumnizedLogLine.cs b/src/ColumnizerLib/ColumnizedLogLine.cs index 41a14e6f..47891d74 100644 --- a/src/ColumnizerLib/ColumnizedLogLine.cs +++ b/src/ColumnizerLib/ColumnizedLogLine.cs @@ -1,13 +1,12 @@ -namespace LogExpert +namespace LogExpert; + +public class ColumnizedLogLine : IColumnizedLogLine { - public class ColumnizedLogLine : IColumnizedLogLine - { - #region Properties + #region Properties - public ILogLine LogLine { get; set; } + public ILogLine LogLine { get; set; } - public IColumn[] ColumnValues { get; set; } + public IColumn[] ColumnValues { get; set; } - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/Extensions/LogLineExtensions.cs b/src/ColumnizerLib/Extensions/LogLineExtensions.cs index 44077eb7..659ff75e 100644 --- a/src/ColumnizerLib/Extensions/LogLineExtensions.cs +++ b/src/ColumnizerLib/Extensions/LogLineExtensions.cs @@ -1,10 +1,9 @@ -namespace LogExpert.Extensions +namespace LogExpert.Extensions; + +public static class LogLineExtensions { - public static class LogLineExtensions + public static string ToClipBoardText(this ILogLine logLine) { - public static string ToClipBoardText(this ILogLine logLine) - { - return "\t" + (logLine.LineNumber + 1).ToString() + "\t" + logLine.FullLine; - } + return "\t" + (logLine.LineNumber + 1).ToString() + "\t" + logLine.FullLine; } } \ No newline at end of file diff --git a/src/ColumnizerLib/IAutoLogLineColumnizerCallback.cs b/src/ColumnizerLib/IAutoLogLineColumnizerCallback.cs index 25b315d9..7206b8c9 100644 --- a/src/ColumnizerLib/IAutoLogLineColumnizerCallback.cs +++ b/src/ColumnizerLib/IAutoLogLineColumnizerCallback.cs @@ -1,12 +1,11 @@ -namespace LogExpert +namespace LogExpert; + +public interface IAutoLogLineColumnizerCallback { - public interface IAutoLogLineColumnizerCallback - { - /// - /// Returns the log line with the given index (zero-based). - /// - /// Number of the line to be retrieved - /// A string with line content or null if line number is out of range - ILogLine GetLogLine (int lineNum); - } + /// + /// Returns the log line with the given index (zero-based). + /// + /// Number of the line to be retrieved + /// A string with line content or null if line number is out of range + ILogLine GetLogLine (int lineNum); } \ No newline at end of file diff --git a/src/ColumnizerLib/IColumn.cs b/src/ColumnizerLib/IColumn.cs index d9abc0ab..57ba40bd 100644 --- a/src/ColumnizerLib/IColumn.cs +++ b/src/ColumnizerLib/IColumn.cs @@ -3,18 +3,17 @@ using System.Linq; using System.Text; -namespace LogExpert +namespace LogExpert; + +public interface IColumn : ITextValue { - public interface IColumn : ITextValue - { - #region Properties + #region Properties - IColumnizedLogLine Parent { get; } + IColumnizedLogLine Parent { get; } - string FullValue { get; } + string FullValue { get; } - string DisplayValue { get; } + string DisplayValue { get; } - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/IColumnizedLogLine.cs b/src/ColumnizerLib/IColumnizedLogLine.cs index 491c78f3..dad1ee46 100644 --- a/src/ColumnizerLib/IColumnizedLogLine.cs +++ b/src/ColumnizerLib/IColumnizedLogLine.cs @@ -3,17 +3,16 @@ using System.Linq; using System.Text; -namespace LogExpert +namespace LogExpert; + +public interface IColumnizedLogLine { - public interface IColumnizedLogLine - { - #region Properties + #region Properties - ILogLine LogLine { get; } + ILogLine LogLine { get; } - IColumn[] ColumnValues { get; } + IColumn[] ColumnValues { get; } - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/IColumnizerConfigurator.cs b/src/ColumnizerLib/IColumnizerConfigurator.cs index a9a953e2..a9249d06 100644 --- a/src/ColumnizerLib/IColumnizerConfigurator.cs +++ b/src/ColumnizerLib/IColumnizerConfigurator.cs @@ -1,46 +1,45 @@  -namespace LogExpert +namespace LogExpert; + +/// +/// A Columnizer can implement this interface if it has to show an own settings dialog to the user. +/// The Config button in LogExpert's columnizer dialog is enabled if a Columnizer implements this interface. +/// If you don't need a config dialog you don't have to implement this interface. +/// +public interface IColumnizerConfigurator { + #region Public methods + /// - /// A Columnizer can implement this interface if it has to show an own settings dialog to the user. - /// The Config button in LogExpert's columnizer dialog is enabled if a Columnizer implements this interface. - /// If you don't need a config dialog you don't have to implement this interface. + /// This function is called if the user presses the Config button on the Columnizer dialog. + /// Its up to the Columnizer plugin to show an own configuration dialog and store all + /// required settings. /// - public interface IColumnizerConfigurator - { - #region Public methods - - /// - /// This function is called if the user presses the Config button on the Columnizer dialog. - /// Its up to the Columnizer plugin to show an own configuration dialog and store all - /// required settings. - /// - /// Callback interface with functions which can be used by the columnizer - /// The complete path to the directory where LogExpert stores its settings. - /// You can use this directory, if you want to. Please don't use the file name "settings.dat", because this - /// name is used by LogExpert. - /// - /// - /// This is the place to show a configuration dialog to the user. You have to handle all dialog stuff by yourself. - /// It's also your own job to store the configuration in a config file or on the registry. - /// The callback is passed to this function just in case you need the file name of the current log file - /// or the line count etc. You can also use it to store different settings for every log file. - /// You can use the callback to distinguish between different files. Its passed to all important - /// functions in the Columnizer. - /// - void Configure(ILogLineColumnizerCallback callback, string configDir); + /// Callback interface with functions which can be used by the columnizer + /// The complete path to the directory where LogExpert stores its settings. + /// You can use this directory, if you want to. Please don't use the file name "settings.dat", because this + /// name is used by LogExpert. + /// + /// + /// This is the place to show a configuration dialog to the user. You have to handle all dialog stuff by yourself. + /// It's also your own job to store the configuration in a config file or on the registry. + /// The callback is passed to this function just in case you need the file name of the current log file + /// or the line count etc. You can also use it to store different settings for every log file. + /// You can use the callback to distinguish between different files. Its passed to all important + /// functions in the Columnizer. + /// + void Configure(ILogLineColumnizerCallback callback, string configDir); - /// - /// This function will be called right after LogExpert has loaded your Columnizer class. Use this - /// to load the configuration which was saved in the Configure() function. - /// You have to hold the loaded config data in your Columnizer object. - /// - /// The complete path to the directory where LogExpert stores its settings. - /// You can use this directory, if you want to. Please don't use the file name "settings.dat", because this - /// name is used by LogExpert. - /// - void LoadConfig(string configDir); + /// + /// This function will be called right after LogExpert has loaded your Columnizer class. Use this + /// to load the configuration which was saved in the Configure() function. + /// You have to hold the loaded config data in your Columnizer object. + /// + /// The complete path to the directory where LogExpert stores its settings. + /// You can use this directory, if you want to. Please don't use the file name "settings.dat", because this + /// name is used by LogExpert. + /// + void LoadConfig(string configDir); - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/IColumnizerPriority.cs b/src/ColumnizerLib/IColumnizerPriority.cs index 5cf85770..2ee01840 100644 --- a/src/ColumnizerLib/IColumnizerPriority.cs +++ b/src/ColumnizerLib/IColumnizerPriority.cs @@ -3,16 +3,15 @@ using System.Linq; using System.Text; -namespace LogExpert +namespace LogExpert; + +public interface IColumnizerPriority { - public interface IColumnizerPriority - { - /// - /// Get the priority for this columnizer so the up layer can decide which columnizer is the best fitted one. - /// - /// - /// - /// - Priority GetPriority(string fileName, IEnumerable samples); - } + /// + /// Get the priority for this columnizer so the up layer can decide which columnizer is the best fitted one. + /// + /// + /// + /// + Priority GetPriority(string fileName, IEnumerable samples); } \ No newline at end of file diff --git a/src/ColumnizerLib/IContextMenuEntry.cs b/src/ColumnizerLib/IContextMenuEntry.cs index c23f78c7..bc59df1e 100644 --- a/src/ColumnizerLib/IContextMenuEntry.cs +++ b/src/ColumnizerLib/IContextMenuEntry.cs @@ -1,58 +1,57 @@ using System.Collections.Generic; -namespace LogExpert +namespace LogExpert; + +/// +/// Implement this interface to add a menu entry to the context menu of LogExpert. +/// +/// +/// +/// The methods in this interface will be called in the GUI thread. So make sure that there's no +/// heavyweight work to do in your implementations. +/// +/// +public interface IContextMenuEntry { + #region Public methods + /// - /// Implement this interface to add a menu entry to the context menu of LogExpert. + /// This function is called from LogExpert if the context menu is about to be displayed. + /// Your implementation can control whether LogExpert will show a menu entry by returning + /// an appropriate value.

///
- /// - /// - /// The methods in this interface will be called in the GUI thread. So make sure that there's no - /// heavyweight work to do in your implementations. - /// - /// - public interface IContextMenuEntry - { - #region Public methods - - /// - /// This function is called from LogExpert if the context menu is about to be displayed. - /// Your implementation can control whether LogExpert will show a menu entry by returning - /// an appropriate value.

- ///
- /// A list containing all selected line numbers. - /// The currently selected Columnizer. You can use it to split log lines, - /// if necessary. - /// The callback interface implemented by LogExpert. You can use the functions - /// for retrieving log lines or pass it along to functions of the Columnizer if needed. - /// - /// Return the string which should be displayed in the context menu.

- /// You can control the menu behaviour by returning the the following values:

- ///
    - ///
  • Normal string: The string is displayed as a menu entry
  • - ///
  • String starting with underscore: The string is displayed as a disabled menu entry
  • - ///
  • null: No menu entry is displayed.
  • - ///
- ///
- string GetMenuText(IList lines, ILogLineColumnizer columnizer, ILogExpertCallback callback); - - string GetMenuText(int linesCount, ILogLineColumnizer columnizer, ILogLine line); - - - /// - /// This function is called from LogExpert if the menu entry is choosen by the user.

- /// Note that this function is called from the GUI thread. So try to avoid time consuming operations. - ///
- /// A list containing all selected line numbers. - /// The currently selected Columnizer. You can use it to split log lines, - /// if necessary. - /// The callback interface implemented by LogExpert. You can use the functions - /// for retrieving log lines or pass it along to functions of the Columnizer if needed. - void MenuSelected(IList lines, ILogLineColumnizer columnizer, ILogExpertCallback callback); - - void MenuSelected(int linesCount, ILogLineColumnizer columnizer, ILogLine line); - - #endregion - } + /// A list containing all selected line numbers. + /// The currently selected Columnizer. You can use it to split log lines, + /// if necessary. + /// The callback interface implemented by LogExpert. You can use the functions + /// for retrieving log lines or pass it along to functions of the Columnizer if needed. + /// + /// Return the string which should be displayed in the context menu.

+ /// You can control the menu behaviour by returning the the following values:

+ ///
    + ///
  • Normal string: The string is displayed as a menu entry
  • + ///
  • String starting with underscore: The string is displayed as a disabled menu entry
  • + ///
  • null: No menu entry is displayed.
  • + ///
+ ///
+ string GetMenuText(IList lines, ILogLineColumnizer columnizer, ILogExpertCallback callback); + + string GetMenuText(int linesCount, ILogLineColumnizer columnizer, ILogLine line); + + + /// + /// This function is called from LogExpert if the menu entry is choosen by the user.

+ /// Note that this function is called from the GUI thread. So try to avoid time consuming operations. + ///
+ /// A list containing all selected line numbers. + /// The currently selected Columnizer. You can use it to split log lines, + /// if necessary. + /// The callback interface implemented by LogExpert. You can use the functions + /// for retrieving log lines or pass it along to functions of the Columnizer if needed. + void MenuSelected(IList lines, ILogLineColumnizer columnizer, ILogExpertCallback callback); + + void MenuSelected(int linesCount, ILogLineColumnizer columnizer, ILogLine line); + + #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/IFileSystemCallback.cs b/src/ColumnizerLib/IFileSystemCallback.cs index bac789b7..faac1728 100644 --- a/src/ColumnizerLib/IFileSystemCallback.cs +++ b/src/ColumnizerLib/IFileSystemCallback.cs @@ -2,21 +2,20 @@ using System.Collections.Generic; using System.Text; -namespace LogExpert +namespace LogExpert; + +/// +/// Service interface implemented by LogExpert. This can be used by IFileSystemPlugin implementations to get certain services. +/// +public interface IFileSystemCallback { + #region Public methods + /// - /// Service interface implemented by LogExpert. This can be used by IFileSystemPlugin implementations to get certain services. + /// Retrieve a logger. The plugin can use the logger to write log messages into LogExpert's log file. /// - public interface IFileSystemCallback - { - #region Public methods - - /// - /// Retrieve a logger. The plugin can use the logger to write log messages into LogExpert's log file. - /// - /// - ILogExpertLogger GetLogger(); + /// + ILogExpertLogger GetLogger(); - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/IFileSystemPlugin.cs b/src/ColumnizerLib/IFileSystemPlugin.cs index 985edf9b..8e86be48 100644 --- a/src/ColumnizerLib/IFileSystemPlugin.cs +++ b/src/ColumnizerLib/IFileSystemPlugin.cs @@ -1,46 +1,45 @@ -namespace LogExpert +namespace LogExpert; + +/// +/// Interface for file system plugins. A file system plugin is responsible for feeding file data to LogExpert. +/// +/// +/// LogExperts file handling is done via file system plugins. The selection if the appropriate plugin for a file is based +/// on URI schemes. If a file system plugin returns true to the method, it will be selected +/// to handle a file. +/// +public interface IFileSystemPlugin { + #region Properties + + /// + /// Name of the plugin. Will be used in the Settings dialog. + /// + string Text { get; } + + /// + /// Short description. Currently unused, but maybe used later for displaying a short info about the plugin. + /// + string Description { get; } + + #endregion + + #region Public methods + /// - /// Interface for file system plugins. A file system plugin is responsible for feeding file data to LogExpert. + /// Called from LogExpert to determine a file system plugin for a given URI. /// - /// - /// LogExperts file handling is done via file system plugins. The selection if the appropriate plugin for a file is based - /// on URI schemes. If a file system plugin returns true to the method, it will be selected - /// to handle a file. - /// - public interface IFileSystemPlugin - { - #region Properties - - /// - /// Name of the plugin. Will be used in the Settings dialog. - /// - string Text { get; } - - /// - /// Short description. Currently unused, but maybe used later for displaying a short info about the plugin. - /// - string Description { get; } - - #endregion - - #region Public methods - - /// - /// Called from LogExpert to determine a file system plugin for a given URI. - /// - /// The URI of the file to be loaded. - /// Return true if the file system plugin can handle the URI. - bool CanHandleUri(string uriString); - - /// - /// Return a file system specific implementation of here. - /// The method is called from LogExpert when a file is about to be opened. It's called after was called. - /// - /// - /// - ILogFileInfo GetLogfileInfo(string uriString); - - #endregion - } + /// The URI of the file to be loaded. + /// Return true if the file system plugin can handle the URI. + bool CanHandleUri(string uriString); + + /// + /// Return a file system specific implementation of here. + /// The method is called from LogExpert when a file is about to be opened. It's called after was called. + /// + /// + /// + ILogFileInfo GetLogfileInfo(string uriString); + + #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/IInitColumnizer.cs b/src/ColumnizerLib/IInitColumnizer.cs index 6c90ae49..586f9af5 100644 --- a/src/ColumnizerLib/IInitColumnizer.cs +++ b/src/ColumnizerLib/IInitColumnizer.cs @@ -2,41 +2,40 @@ using System.Collections.Generic; using System.Text; -namespace LogExpert +namespace LogExpert; + +/// +/// Implement this interface in your columnizer if you need to do some initialization work +/// every time the columnizer is selected. +/// +/// +/// +/// The methods in this interface will be called in the GUI thread. So make sure that there's no +/// heavyweight work to do in your implementations. +/// +/// If a file is reloaded, the current Columnizer is set again. That means that the methods of this +/// interface will be called again. Generally you should do no assumptions about how often the +/// methods will be called. The file is already loaded when the columnizer is set. So +/// you can use the methods in the given callbacks to get informations about the file or to +/// retrieve specific lines. +/// +/// +public interface IInitColumnizer { + #region Public methods + /// - /// Implement this interface in your columnizer if you need to do some initialization work - /// every time the columnizer is selected. + /// This method is called when the Columnizer is selected as the current columnizer. /// - /// - /// - /// The methods in this interface will be called in the GUI thread. So make sure that there's no - /// heavyweight work to do in your implementations. - /// - /// If a file is reloaded, the current Columnizer is set again. That means that the methods of this - /// interface will be called again. Generally you should do no assumptions about how often the - /// methods will be called. The file is already loaded when the columnizer is set. So - /// you can use the methods in the given callbacks to get informations about the file or to - /// retrieve specific lines. - /// - /// - public interface IInitColumnizer - { - #region Public methods - - /// - /// This method is called when the Columnizer is selected as the current columnizer. - /// - /// Callback that can be used to retrieve some informations, if needed. - void Selected(ILogLineColumnizerCallback callback); + /// Callback that can be used to retrieve some informations, if needed. + void Selected(ILogLineColumnizerCallback callback); - /// - /// This method is called when the Columnizer is de-selected (i.e. when another Columnizer is - /// selected). - /// - /// Callback that can be used to retrieve some informations, if needed. - void DeSelected(ILogLineColumnizerCallback callback); + /// + /// This method is called when the Columnizer is de-selected (i.e. when another Columnizer is + /// selected). + /// + /// Callback that can be used to retrieve some informations, if needed. + void DeSelected(ILogLineColumnizerCallback callback); - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/IKeywordAction.cs b/src/ColumnizerLib/IKeywordAction.cs index 1329f36d..04d6259d 100644 --- a/src/ColumnizerLib/IKeywordAction.cs +++ b/src/ColumnizerLib/IKeywordAction.cs @@ -2,50 +2,49 @@ using System.Collections.Generic; using System.Text; -namespace LogExpert +namespace LogExpert; + +/// +/// Implement this interface to execute a self defined action when LogExpert detects a +/// keyword on incomig log file content. +/// These kind of plugins can be used in the "Highlight and Action Triggers" dialog. +/// +public interface IKeywordAction { + #region Public methods + /// - /// Implement this interface to execute a self defined action when LogExpert detects a - /// keyword on incomig log file content. - /// These kind of plugins can be used in the "Highlight and Action Triggers" dialog. + /// Is called when LogExpert detects a keyword match which is configured for this plugin. + /// The keywords are configured in the Highlight dialog. + /// You have to implement this method to execute your desired actions. /// - public interface IKeywordAction - { - #region Public methods + /// The keyword which triggered the call. + /// The parameter configured for the plugin launch (in the Highlight dialog). + /// A callback which can be used by the plugin. + /// The current columnizer. Can be used to obtain timestamps + /// (if supported by Columnizer) or to split the log line into fields. + /// + /// This method is called in a background thread from the process' thread pool (using BeginInvoke()). + /// So you cannot rely on state information retrieved by the given callback. E.g. the line count + /// may change during the execution of the method. The only exception from this rule is the current line number + /// retrieved from the callback. This is of course the line number of the line that has triggered + /// the keyword match. + /// + void Execute(string keyword, string param, ILogExpertCallback callback, ILogLineColumnizer columnizer); - /// - /// Is called when LogExpert detects a keyword match which is configured for this plugin. - /// The keywords are configured in the Highlight dialog. - /// You have to implement this method to execute your desired actions. - /// - /// The keyword which triggered the call. - /// The parameter configured for the plugin launch (in the Highlight dialog). - /// A callback which can be used by the plugin. - /// The current columnizer. Can be used to obtain timestamps - /// (if supported by Columnizer) or to split the log line into fields. - /// - /// This method is called in a background thread from the process' thread pool (using BeginInvoke()). - /// So you cannot rely on state information retrieved by the given callback. E.g. the line count - /// may change during the execution of the method. The only exception from this rule is the current line number - /// retrieved from the callback. This is of course the line number of the line that has triggered - /// the keyword match. - /// - void Execute(string keyword, string param, ILogExpertCallback callback, ILogLineColumnizer columnizer); - - /// - /// Return the name of your plugin here. The returned name is used for displaying the plugin list - /// in the settings. - /// - /// The name of the plugin. - string GetName(); + /// + /// Return the name of your plugin here. The returned name is used for displaying the plugin list + /// in the settings. + /// + /// The name of the plugin. + string GetName(); - /// - /// Return a description of your plugin here. E.g. a short explanation of parameters. The descriptions - /// will be displayed in the plugin chooser dialog which is used by the Highlight settings. - /// - /// The description of the plugin. - string GetDescription(); + /// + /// Return a description of your plugin here. E.g. a short explanation of parameters. The descriptions + /// will be displayed in the plugin chooser dialog which is used by the Highlight settings. + /// + /// The description of the plugin. + string GetDescription(); - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/ILogExpertCallback.cs b/src/ColumnizerLib/ILogExpertCallback.cs index 9f1a96d9..d1ddca26 100644 --- a/src/ColumnizerLib/ILogExpertCallback.cs +++ b/src/ColumnizerLib/ILogExpertCallback.cs @@ -1,66 +1,65 @@ using System.Collections.Generic; -namespace LogExpert +namespace LogExpert; + +/// +/// This callback interface is implemented by LogExpert. You can use it e.g. when implementing a +/// context menu plugin. +/// +public interface ILogExpertCallback : ILogLineColumnizerCallback { + #region Public methods + /// - /// This callback interface is implemented by LogExpert. You can use it e.g. when implementing a - /// context menu plugin. + /// Call this function to add a new temporary file tab to LogExpert. This may be usefull + /// if your plugin creates some output into a file which has to be shown in LogExpert. /// - public interface ILogExpertCallback : ILogLineColumnizerCallback - { - #region Public methods + /// Path of the file to be loaded. + /// Title shown on the tab. + /// + /// The file tab is internally handled like the temp file tabs which LogExpert uses for + /// FilterTabs or clipboard copy tabs. + /// This has some implications: + ///
    + ///
  • The file path is not shown. Only the title is shown.
  • + ///
  • The encoding of the file is expected to be 2-byte Unicode!
  • + ///
  • The file will not be added to the history of opened files.
  • + ///
  • The file will be deleted when closing the tab!
  • + ///
+ ///
+ void AddTempFileTab(string fileName, string title); - /// - /// Call this function to add a new temporary file tab to LogExpert. This may be usefull - /// if your plugin creates some output into a file which has to be shown in LogExpert. - /// - /// Path of the file to be loaded. - /// Title shown on the tab. - /// - /// The file tab is internally handled like the temp file tabs which LogExpert uses for - /// FilterTabs or clipboard copy tabs. - /// This has some implications: - ///
    - ///
  • The file path is not shown. Only the title is shown.
  • - ///
  • The encoding of the file is expected to be 2-byte Unicode!
  • - ///
  • The file will not be added to the history of opened files.
  • - ///
  • The file will be deleted when closing the tab!
  • - ///
- ///
- void AddTempFileTab(string fileName, string title); - - /// - /// With this function you can create a new tab and add a bunch of text lines to it. - /// - /// A list with LineEntry items containing text and an - /// optional reference to the original file location. - /// The title for the new tab. - /// - /// - /// The lines are given by a list of . If you set the lineNumber field - /// in each LineEntry to a lineNumber of the original logfile (the logfile for which the context - /// menu is called for), you can create a 'link' from the line of your 'target output' to a line - /// in the 'source tab'. - /// - /// - /// The user can then navigate from the line in the new tab to the referenced - /// line in the original file (by using "locate in original file" from the context menu). - /// This is especially useful for plugins that generate output lines which are directly associated - /// to the selected input lines. - /// - /// - /// If you can't provide a reference to a location in the logfile, set the line number to -1. This - /// will disable the "locate in original file" menu entry. - /// - /// - void AddPipedTab(IList lineEntryList, string title); + /// + /// With this function you can create a new tab and add a bunch of text lines to it. + /// + /// A list with LineEntry items containing text and an + /// optional reference to the original file location. + /// The title for the new tab. + /// + /// + /// The lines are given by a list of . If you set the lineNumber field + /// in each LineEntry to a lineNumber of the original logfile (the logfile for which the context + /// menu is called for), you can create a 'link' from the line of your 'target output' to a line + /// in the 'source tab'. + /// + /// + /// The user can then navigate from the line in the new tab to the referenced + /// line in the original file (by using "locate in original file" from the context menu). + /// This is especially useful for plugins that generate output lines which are directly associated + /// to the selected input lines. + /// + /// + /// If you can't provide a reference to a location in the logfile, set the line number to -1. This + /// will disable the "locate in original file" menu entry. + /// + /// + void AddPipedTab(IList lineEntryList, string title); - /// - /// Returns the title of the current tab (the tab for which the context menu plugin was called for). - /// - /// - string GetTabTitle(); + /// + /// Returns the title of the current tab (the tab for which the context menu plugin was called for). + /// + /// + string GetTabTitle(); - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/ILogExpertLogger.cs b/src/ColumnizerLib/ILogExpertLogger.cs index aec36cfe..cb9405d2 100644 --- a/src/ColumnizerLib/ILogExpertLogger.cs +++ b/src/ColumnizerLib/ILogExpertLogger.cs @@ -2,43 +2,42 @@ using System.Collections.Generic; using System.Text; -namespace LogExpert +namespace LogExpert; + +/// +/// Simple Logger interface to let plugins log into LogExpert's application log file. +/// +public interface ILogExpertLogger { + #region Public methods + /// - /// Simple Logger interface to let plugins log into LogExpert's application log file. + /// Logs a message on INFO level to LogExpert#s log file. The logfile is only active in debug builds. + /// The logger in LogExpert will automatically add the class and the method name of the caller. /// - public interface ILogExpertLogger - { - #region Public methods - - /// - /// Logs a message on INFO level to LogExpert#s log file. The logfile is only active in debug builds. - /// The logger in LogExpert will automatically add the class and the method name of the caller. - /// - /// A message to be logged. - void Info(string msg); + /// A message to be logged. + void Info(string msg); - /// - /// Logs a message on DEBUG level to LogExpert#s log file. The logfile is only active in debug builds. - /// The logger in LogExpert will automatically add the class and the method name of the caller. - /// - /// A message to be logged. - void Debug(string msg); + /// + /// Logs a message on DEBUG level to LogExpert#s log file. The logfile is only active in debug builds. + /// The logger in LogExpert will automatically add the class and the method name of the caller. + /// + /// A message to be logged. + void Debug(string msg); - /// - /// Logs a message on WARN level to LogExpert#s log file. The logfile is only active in debug builds. - /// The logger in LogExpert will automatically add the class and the method name of the caller. - /// - /// A message to be logged. - void LogWarn(string msg); + /// + /// Logs a message on WARN level to LogExpert#s log file. The logfile is only active in debug builds. + /// The logger in LogExpert will automatically add the class and the method name of the caller. + /// + /// A message to be logged. + void LogWarn(string msg); - /// - /// Logs a message on ERROR level to LogExpert#s log file. The logfile is only active in debug builds. - /// The logger in LogExpert will automatically add the class and the method name of the caller. - /// - /// A message to be logged. - void LogError(string msg); + /// + /// Logs a message on ERROR level to LogExpert#s log file. The logfile is only active in debug builds. + /// The logger in LogExpert will automatically add the class and the method name of the caller. + /// + /// A message to be logged. + void LogError(string msg); - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/ILogExpertPlugin.cs b/src/ColumnizerLib/ILogExpertPlugin.cs index 041e64d5..51c40971 100644 --- a/src/ColumnizerLib/ILogExpertPlugin.cs +++ b/src/ColumnizerLib/ILogExpertPlugin.cs @@ -2,27 +2,26 @@ using System.Collections.Generic; using System.Text; -namespace LogExpert +namespace LogExpert; + +/// +/// Implement this interface to get notified of various global events in LogExpert. +/// The interface can be implemented by all currently known type of LogExpert plugins (Columnizers, +/// keyword plugins, context menu plugins). +/// +public interface ILogExpertPlugin { + #region Public methods + /// - /// Implement this interface to get notified of various global events in LogExpert. - /// The interface can be implemented by all currently known type of LogExpert plugins (Columnizers, - /// keyword plugins, context menu plugins). + /// Called on application exit. May be used for cleanup purposes, /// - public interface ILogExpertPlugin - { - #region Public methods - - /// - /// Called on application exit. May be used for cleanup purposes, - /// - void AppExiting(); + void AppExiting(); - /// - /// Called when the plugin is loaded at plugin registration while LogExpert startup. - /// - void PluginLoaded(); + /// + /// Called when the plugin is loaded at plugin registration while LogExpert startup. + /// + void PluginLoaded(); - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/ILogExpertPluginConfigurator.cs b/src/ColumnizerLib/ILogExpertPluginConfigurator.cs index c142541b..9981528c 100644 --- a/src/ColumnizerLib/ILogExpertPluginConfigurator.cs +++ b/src/ColumnizerLib/ILogExpertPluginConfigurator.cs @@ -2,92 +2,91 @@ using System.Collections.Generic; using System.Text; -namespace LogExpert +namespace LogExpert; + +/// +/// If your context menu plugin or keyword action plugin has some configuration it should +/// implement this interface. +/// When your plugin has implemented this interface, it will get notified if it has to +/// show a config dialog and to save/load config data.

+/// Like in the IColumnizerConfigurator, you have to do all the saving and loading stuff +/// by yourself. +///
+public interface ILogExpertPluginConfigurator { + #region Public methods + /// - /// If your context menu plugin or keyword action plugin has some configuration it should - /// implement this interface. - /// When your plugin has implemented this interface, it will get notified if it has to - /// show a config dialog and to save/load config data.

- /// Like in the IColumnizerConfigurator, you have to do all the saving and loading stuff - /// by yourself. + /// Return whether your plugin will provide an embedded config dialog or wants to provide + /// a 'popup' dialog for the configuration.



+ /// 'Embedded' means that the dialog is shown directly in the Settings dialog of LogExpert on the + /// right pane of the plugin config tab. ///
- public interface ILogExpertPluginConfigurator - { - #region Public methods + /// Return true if your plugin config dialog should be displayed embedded. + bool HasEmbeddedForm(); - /// - /// Return whether your plugin will provide an embedded config dialog or wants to provide - /// a 'popup' dialog for the configuration.



- /// 'Embedded' means that the dialog is shown directly in the Settings dialog of LogExpert on the - /// right pane of the plugin config tab. - ///
- /// Return true if your plugin config dialog should be displayed embedded. - bool HasEmbeddedForm(); - - /// - /// This function is called when LogExpert fills the list of plugins in the Settings dialog. - /// This is the right time to create a 'temporary copy' of your current settings. The temporary copy - /// can be used for initializing the config dialogs. - /// - void StartConfig(); + /// + /// This function is called when LogExpert fills the list of plugins in the Settings dialog. + /// This is the right time to create a 'temporary copy' of your current settings. The temporary copy + /// can be used for initializing the config dialogs. + /// + void StartConfig(); - /// - /// Implement this function if your plugins uses an embedded config dialog. - /// This function is called when the user selects the plugin in the list of the Settings dialog - /// and the plugin uses an embedded dialog.



- /// You have to create a non-toplevel dialog and set the given parentPanel as the parent of your - /// dialog. Then make your dialog visible (using Show()). - /// You don't need an OK or Cancel button. Changes made in the dialog should be retrieved - /// to a temporary config every time the function is called. - /// The temporary config should be permanently stored when the function - /// is called. - ///
- /// - /// Set this panel as the parent for you config dialog. - void ShowConfigForm(object parentPanel); + /// + /// Implement this function if your plugins uses an embedded config dialog. + /// This function is called when the user selects the plugin in the list of the Settings dialog + /// and the plugin uses an embedded dialog.



+ /// You have to create a non-toplevel dialog and set the given parentPanel as the parent of your + /// dialog. Then make your dialog visible (using Show()). + /// You don't need an OK or Cancel button. Changes made in the dialog should be retrieved + /// to a temporary config every time the function is called. + /// The temporary config should be permanently stored when the function + /// is called. + ///
+ /// + /// Set this panel as the parent for you config dialog. + void ShowConfigForm(object parentPanel); - /// - /// Implement this function if your plugin uses an own top level dialog for the configuration (modal config dialog). - /// This function is called if the user clicks on the 'Config' button on the plugin settings. - ///



- /// You have to create a top level dialog and set the given Form as the owner. Then show - /// the dialog as a modal window (Form.ShowDialog()). Changes made in the dialog should be retrieved - /// after Form.ShowDialog() returns and then put to the temporary copy of your config. - /// The temporary copy config should be permanently stored when the function - /// is called. - ///
- /// - /// Set the given Form as the owner of your dialog. - void ShowConfigDialog(object owner); + /// + /// Implement this function if your plugin uses an own top level dialog for the configuration (modal config dialog). + /// This function is called if the user clicks on the 'Config' button on the plugin settings. + ///



+ /// You have to create a top level dialog and set the given Form as the owner. Then show + /// the dialog as a modal window (Form.ShowDialog()). Changes made in the dialog should be retrieved + /// after Form.ShowDialog() returns and then put to the temporary copy of your config. + /// The temporary copy config should be permanently stored when the function + /// is called. + ///
+ /// + /// Set the given Form as the owner of your dialog. + void ShowConfigDialog(object owner); - /// - /// This function is called when the user selects another plugin in the list. You should retrieve - /// the changes made in the config dialog to a temporary copy of the config and destroy your dialog. - /// Don't make the changes permanent here, because the user may click the cancel button of LogExpert's - /// Settings dialog. In this case he/she would expect the changes to be discarded.

- /// The right place for making changes permanent is the function. - ///
- /// - /// The method is also called when the settings dialog is closed. If the settings dialog is closed - /// by OK button this method is called before the method. - /// - void HideConfigForm(); + /// + /// This function is called when the user selects another plugin in the list. You should retrieve + /// the changes made in the config dialog to a temporary copy of the config and destroy your dialog. + /// Don't make the changes permanent here, because the user may click the cancel button of LogExpert's + /// Settings dialog. In this case he/she would expect the changes to be discarded.

+ /// The right place for making changes permanent is the function. + ///
+ /// + /// The method is also called when the settings dialog is closed. If the settings dialog is closed + /// by OK button this method is called before the method. + /// + void HideConfigForm(); - /// - /// Called by LogExpert if the user clicks the OK button in LogExpert's Settings dialog. - /// Save your temporary copy of the config here. - /// - /// The location where LogExpert stores its settings. - void SaveConfig(string configDir); + /// + /// Called by LogExpert if the user clicks the OK button in LogExpert's Settings dialog. + /// Save your temporary copy of the config here. + /// + /// The location where LogExpert stores its settings. + void SaveConfig(string configDir); - /// - /// This function is called when LogExpert is started and scans the plugin directory. - /// You should load your settings here. - /// - /// The location where LogExpert stores its settings. - void LoadConfig(string configDir); + /// + /// This function is called when LogExpert is started and scans the plugin directory. + /// You should load your settings here. + /// + /// The location where LogExpert stores its settings. + void LoadConfig(string configDir); - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/ILogFileInfo.cs b/src/ColumnizerLib/ILogFileInfo.cs index 8a028472..a65ee5b1 100644 --- a/src/ColumnizerLib/ILogFileInfo.cs +++ b/src/ColumnizerLib/ILogFileInfo.cs @@ -1,85 +1,84 @@ using System; using System.IO; -namespace LogExpert +namespace LogExpert; + +/// +/// Interface which represents a file in LogExpert. 'File' could be anything that represents text data to be displayed in LogExpert. +/// +public interface ILogFileInfo { + #region Properties + + /// + /// The file name (complete path) of the log file. This should be a unique name. E.g. an URI or a path on local disk. + /// + string FullName { get; } + + /// + /// The file name without path. + /// + string FileName { get; } + + /// + /// The directory of the log file. In most cases this is the FullName minus FileName. + /// + string DirectoryName { get; } + + /// + /// Character used to separate directories in a path string. + /// + char DirectorySeparatorChar { get; } + /// - /// Interface which represents a file in LogExpert. 'File' could be anything that represents text data to be displayed in LogExpert. + /// The URI of the log file. /// - public interface ILogFileInfo - { - #region Properties - - /// - /// The file name (complete path) of the log file. This should be a unique name. E.g. an URI or a path on local disk. - /// - string FullName { get; } - - /// - /// The file name without path. - /// - string FileName { get; } - - /// - /// The directory of the log file. In most cases this is the FullName minus FileName. - /// - string DirectoryName { get; } - - /// - /// Character used to separate directories in a path string. - /// - char DirectorySeparatorChar { get; } - - /// - /// The URI of the log file. - /// - Uri Uri { get; } - - /// - /// Current length of the file. Return -1 if the file is not found. - /// - long Length { get; } - - /// - /// Initial file length at the time the ILogFileInfo instance was created. This is used for the buffer shifting when - /// using the multi file feature. This value should not change after the instance has been created. - /// - long OriginalLength { get; } - - /// - /// Whether the file exists. - /// - bool FileExists { get; } - - /// - /// The interval (in ms) LogExpert should check for file changes. The property is checked by LogExpert repeatedly in the loop which - /// checks for file changes. So you can adjust the poll interval as needed. E.g. you can lower the interval when many changes occur and - /// raise the interval when the file has not been changed for a certain amount of time. - /// - int PollInterval { get; } - - #endregion - - #region Public methods - - /// - /// Returns a stream for the log file file. The actual type of stream depends on the implementation. - /// The caller (LogExpert) is responsible for closing the stream. - /// - /// - /// The returned Stream must support read and seek. Writing is not needed. - /// - /// A Stream open for reading - Stream OpenStream(); - - /// - /// Return true if the file has been changed since the last call to this method. - /// - /// - /// LogExpert will poll this method with the interval returned from PollInterval. - /// - bool FileHasChanged(); - - #endregion - } + Uri Uri { get; } + + /// + /// Current length of the file. Return -1 if the file is not found. + /// + long Length { get; } + + /// + /// Initial file length at the time the ILogFileInfo instance was created. This is used for the buffer shifting when + /// using the multi file feature. This value should not change after the instance has been created. + /// + long OriginalLength { get; } + + /// + /// Whether the file exists. + /// + bool FileExists { get; } + + /// + /// The interval (in ms) LogExpert should check for file changes. The property is checked by LogExpert repeatedly in the loop which + /// checks for file changes. So you can adjust the poll interval as needed. E.g. you can lower the interval when many changes occur and + /// raise the interval when the file has not been changed for a certain amount of time. + /// + int PollInterval { get; } + + #endregion + + #region Public methods + + /// + /// Returns a stream for the log file file. The actual type of stream depends on the implementation. + /// The caller (LogExpert) is responsible for closing the stream. + /// + /// + /// The returned Stream must support read and seek. Writing is not needed. + /// + /// A Stream open for reading + Stream OpenStream(); + + /// + /// Return true if the file has been changed since the last call to this method. + /// + /// + /// LogExpert will poll this method with the interval returned from PollInterval. + /// + bool FileHasChanged(); + + #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/ILogLine.cs b/src/ColumnizerLib/ILogLine.cs index 8ffe7e9f..7599acbf 100644 --- a/src/ColumnizerLib/ILogLine.cs +++ b/src/ColumnizerLib/ILogLine.cs @@ -1,13 +1,12 @@ -namespace LogExpert +namespace LogExpert; + +public interface ILogLine : ITextValue { - public interface ILogLine : ITextValue - { - #region Properties + #region Properties - string FullLine { get; } + string FullLine { get; } - int LineNumber { get; } + int LineNumber { get; } - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/ILogLineColumnizer.cs b/src/ColumnizerLib/ILogLineColumnizer.cs index e12988ac..70ccc8a2 100644 --- a/src/ColumnizerLib/ILogLineColumnizer.cs +++ b/src/ColumnizerLib/ILogLineColumnizer.cs @@ -1,121 +1,120 @@ using System; -namespace LogExpert +namespace LogExpert; + +/// +/// This interface defines a so-called 'Columnizer' for LogExpert. +/// A columnizer splits a single text line into well defined columns. These columns +/// are used in the data grid view of LogExpert. +///



+/// Optionally a columnizer can parse the log line to determine the date/time of +/// the log line (assuming that all log lines have a timestamp). This is needed for +/// some of the features of LogExpert (see user documentation for more information). +///



+/// You can implement your own columnizers for your logfile format, if needed. +///
+public interface ILogLineColumnizer { - /// - /// This interface defines a so-called 'Columnizer' for LogExpert. - /// A columnizer splits a single text line into well defined columns. These columns - /// are used in the data grid view of LogExpert. - ///



- /// Optionally a columnizer can parse the log line to determine the date/time of - /// the log line (assuming that all log lines have a timestamp). This is needed for - /// some of the features of LogExpert (see user documentation for more information). - ///



- /// You can implement your own columnizers for your logfile format, if needed. - ///
- public interface ILogLineColumnizer - { - #region Public methods + #region Public methods - /// - /// Returns the name for the columnizer. This name is used for the columnizer selection dialog. - /// - string GetName(); + /// + /// Returns the name for the columnizer. This name is used for the columnizer selection dialog. + /// + string GetName(); - /// - /// Returns the description of the columnizer. This text is used in the columnizer selection dialog. - /// - string GetDescription(); + /// + /// Returns the description of the columnizer. This text is used in the columnizer selection dialog. + /// + string GetDescription(); - /// - /// Returns the number of columns the columnizer will split lines into. - /// - /// - /// This value does not include the column for displaying the line number. The line number column - /// is added by LogExpert and is not handled by columnizers. - /// - int GetColumnCount(); + /// + /// Returns the number of columns the columnizer will split lines into. + /// + /// + /// This value does not include the column for displaying the line number. The line number column + /// is added by LogExpert and is not handled by columnizers. + /// + int GetColumnCount(); - /// - /// Returns the names of the columns. The returned names are used by LogExpert for the column headers in the data grid view. - /// The names are expected in order from left to right. - /// - string[] GetColumnNames(); + /// + /// Returns the names of the columns. The returned names are used by LogExpert for the column headers in the data grid view. + /// The names are expected in order from left to right. + /// + string[] GetColumnNames(); - /// - /// Given a single line of the logfile this function splits the line content into columns. The function returns - /// a string array containing the splitted content. - /// - /// - /// This function is called by LogExpert for every line that has to be drawn in the grid view. The faster your code - /// handles the splitting, the faster LogExpert can draw the grid view content.

- ///

- /// Notes about timeshift handling:

- /// If your columnizer implementation supports timeshift (see IsTimeshiftImplemented) - /// you have to add the timestamp offset to the columns representing the timestamp (e.g. columns like 'date' and 'time'). - /// In practice this means you have to parse the date/time value of your log line (see GetTimestamp) - /// add the offset and convert the timestamp back to string value(s). - ///
- /// Callback interface with functions which can be used by the columnizer - /// The line content to be splitted - IColumnizedLogLine SplitLine(ILogLineColumnizerCallback callback, ILogLine line); + /// + /// Given a single line of the logfile this function splits the line content into columns. The function returns + /// a string array containing the splitted content. + /// + /// + /// This function is called by LogExpert for every line that has to be drawn in the grid view. The faster your code + /// handles the splitting, the faster LogExpert can draw the grid view content.

+ ///

+ /// Notes about timeshift handling:

+ /// If your columnizer implementation supports timeshift (see IsTimeshiftImplemented) + /// you have to add the timestamp offset to the columns representing the timestamp (e.g. columns like 'date' and 'time'). + /// In practice this means you have to parse the date/time value of your log line (see GetTimestamp) + /// add the offset and convert the timestamp back to string value(s). + ///
+ /// Callback interface with functions which can be used by the columnizer + /// The line content to be splitted + IColumnizedLogLine SplitLine(ILogLineColumnizerCallback callback, ILogLine line); - /// - /// Returns true, if the columnizer supports timeshift handling. - /// - /// - /// If you return true, you also have to implement the function SetTimeOffset(), GetTimeOffset() and GetTimestamp(). - /// You also must handle PushValue() for the column(s) that displays the timestamp. - /// - bool IsTimeshiftImplemented(); + /// + /// Returns true, if the columnizer supports timeshift handling. + /// + /// + /// If you return true, you also have to implement the function SetTimeOffset(), GetTimeOffset() and GetTimestamp(). + /// You also must handle PushValue() for the column(s) that displays the timestamp. + /// + bool IsTimeshiftImplemented(); - /// - /// Sets an offset to be used for displaying timestamp values. You have to implement this function, if - /// your IsTimeshiftImplemented() function return true. - /// - /// - /// You have to store the given value in the Columnizer instance and add this offset to the timestamp column(s) returned by SplitLine() - /// (e.g. in the date and time columns). - /// - /// The timestamp offset in milliseconds. - void SetTimeOffset(int msecOffset); + /// + /// Sets an offset to be used for displaying timestamp values. You have to implement this function, if + /// your IsTimeshiftImplemented() function return true. + /// + /// + /// You have to store the given value in the Columnizer instance and add this offset to the timestamp column(s) returned by SplitLine() + /// (e.g. in the date and time columns). + /// + /// The timestamp offset in milliseconds. + void SetTimeOffset(int msecOffset); - /// - /// Returns the current stored timestamp offset (set by SetTimeOffset()). - /// - int GetTimeOffset(); + /// + /// Returns the current stored timestamp offset (set by SetTimeOffset()). + /// + int GetTimeOffset(); - /// - /// Returns the timestamp value of the given line as a .NET DateTime object. If there's no valid timestamp in the - /// given line you have to return DateTime.MinValue. - /// - /// - /// When implementing this function you have to parse the given log line for a valid date/time to get a DateTime object. - /// Before returning the DateTime object you have to add the offset which was set by SetTimeOffset().

- ///

- /// Note: If not all lines of your log files contain a valid date/time it's recommended to do some fail-fast pre checks before - /// calling the parse functions of DateTime. This saves a lot of time because DateTime.ParseExact() is very slow when fed with - /// invalid input. - ///
- /// Callback interface with functions which can be used by the columnizer - /// The line content which timestamp has to be returned. - DateTime GetTimestamp(ILogLineColumnizerCallback callback, ILogLine line); + /// + /// Returns the timestamp value of the given line as a .NET DateTime object. If there's no valid timestamp in the + /// given line you have to return DateTime.MinValue. + /// + /// + /// When implementing this function you have to parse the given log line for a valid date/time to get a DateTime object. + /// Before returning the DateTime object you have to add the offset which was set by SetTimeOffset().

+ ///

+ /// Note: If not all lines of your log files contain a valid date/time it's recommended to do some fail-fast pre checks before + /// calling the parse functions of DateTime. This saves a lot of time because DateTime.ParseExact() is very slow when fed with + /// invalid input. + ///
+ /// Callback interface with functions which can be used by the columnizer + /// The line content which timestamp has to be returned. + DateTime GetTimestamp(ILogLineColumnizerCallback callback, ILogLine line); - /// - /// This function is called if the user changes a value in a column (edit mode in the log view). - /// The purpose of the function is to determine a new timestamp offset. So you have to handle the - /// call only if the given column displays a timestamp. - /// - /// - /// You should parse both values (oldValue, value) for valid timestamps, determine the time offset and store the offset as - /// the new timeshift offset (and of course use this offset in the GetTimestamp() and SplitLine() functions). - /// - /// Callback interface with functions which can be used by the columnizer - /// The column number which value has changed. - /// The new value. - /// The old value. - void PushValue(ILogLineColumnizerCallback callback, int column, string value, string oldValue); + /// + /// This function is called if the user changes a value in a column (edit mode in the log view). + /// The purpose of the function is to determine a new timestamp offset. So you have to handle the + /// call only if the given column displays a timestamp. + /// + /// + /// You should parse both values (oldValue, value) for valid timestamps, determine the time offset and store the offset as + /// the new timeshift offset (and of course use this offset in the GetTimestamp() and SplitLine() functions). + /// + /// Callback interface with functions which can be used by the columnizer + /// The column number which value has changed. + /// The new value. + /// The old value. + void PushValue(ILogLineColumnizerCallback callback, int column, string value, string oldValue); - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/ILogLineXmlColumnizer.cs b/src/ColumnizerLib/ILogLineXmlColumnizer.cs index cc79e1dd..9ab6845b 100644 --- a/src/ColumnizerLib/ILogLineXmlColumnizer.cs +++ b/src/ColumnizerLib/ILogLineXmlColumnizer.cs @@ -1,77 +1,72 @@ -using System; -using System.Collections.Generic; -using System.Text; +namespace LogExpert; -namespace LogExpert +/// +/// This is the interface for a Columnizer which supports XML log files. This interface extends +/// the interface. +/// LogExpert will automatically load a log file in XML mode if the current Columnizer implements +/// this interface. +/// +/// +/// +/// Note that the ILogLineXmlColumnizer interface is also a marker interface. If the user selects a +/// Columnizer that implements ILogLineXmlColumnizer then the log file will be treatet as XML file. +///

+/// When in XML mode, LogExpert will scan for XML fragmets. These fragments are defined by opening +/// and closing tags (e.g. <log4j:event> and </log4j:event>). Every fragment is +/// transformed by using a XSLT template. The result of the transformation (which may be multi-lined) +/// is splitted into single lines. These single lines are the lines you will see in LogExpert's display. +///
+/// +/// If you implement a XML Columnizer you have to provide the start tag and end tag and a +/// XSLT. Also you have to provide a namespace declaration, if your logfile uses name spaces. +/// All this stuff must be provided by returning a IXmlLogConfiguration in the method. +/// +/// +/// The processing of XML log files is done in the following steps: +///
    +///
  1. LogExpert reads the file and separates it into fragments of XML content using the given +/// start/end tags ()
  2. +///
  3. The fragments will be translated using the given XSLT () +/// The result is one or more lines of text content. These lines will be the lines LogExpert will 'see' +/// in its internal buffer and line management. They will be handled like normal text lines in other +/// (non-XML) log files. +///
  4. +///
  5. The lines will be passed to the usual methods before displaying. So you can handle +/// field splitting in the way known from . +///
  6. +///
+///
+///
+public interface ILogLineXmlColumnizer : ILogLineColumnizer { + #region Public methods + + /// + /// You have to implement this function to provide a configuration for LogExpert's XML reader. + /// + /// + IXmlLogConfiguration GetXmlLogConfiguration (); + /// - /// This is the interface for a Columnizer which supports XML log files. This interface extends - /// the interface. - /// LogExpert will automatically load a log file in XML mode if the current Columnizer implements - /// this interface. + /// Returns the text which should be copied into the clipboard when the user want to copy selected + /// lines to clipboard. /// + /// The line as retrieved from the internal log reader. This is + /// the result of the XSLT processing with your provided stylesheet. + /// + /// Callback which may be used by the Columnizer + /// A string which is placed into the clipboard /// - /// - /// Note that the ILogLineXmlColumnizer interface is also a marker interface. If the user selects a - /// Columnizer that implements ILogLineXmlColumnizer then the log file will be treatet as XML file. + /// This function is intended to convert the representation of a log line produced by XSLT transformation into + /// a format suitable for clipboard. + /// The method can be used in the case that the XSLT transformation result is not very 'human readable'. ///

- /// When in XML mode, LogExpert will scan for XML fragmets. These fragments are defined by opening - /// and closing tags (e.g. <log4j:event> and </log4j:event>). Every fragment is - /// transformed by using a XSLT template. The result of the transformation (which may be multi-lined) - /// is splitted into single lines. These single lines are the lines you will see in LogExpert's display. - ///
- /// - /// If you implement a XML Columnizer you have to provide the start tag and end tag and a - /// XSLT. Also you have to provide a namespace declaration, if your logfile uses name spaces. - /// All this stuff must be provided by returning a IXmlLogConfiguration in the method. - /// - /// - /// The processing of XML log files is done in the following steps: - ///
    - ///
  1. LogExpert reads the file and separates it into fragments of XML content using the given - /// start/end tags ()
  2. - ///
  3. The fragments will be translated using the given XSLT () - /// The result is one or more lines of text content. These lines will be the lines LogExpert will 'see' - /// in its internal buffer and line management. They will be handled like normal text lines in other - /// (non-XML) log files. - ///
  4. - ///
  5. The lines will be passed to the usual methods before displaying. So you can handle - /// field splitting in the way known from . - ///
  6. - ///
- ///
+ /// An example is the included Log4jXMLColumnizer. It uses special characters to separate the fields. + /// The characters are added while XSLT transformation. The usual Columnizer functions (e.g. SplitLIne()) will + /// use these markers for line splitting. + /// When copying to clipboard, this method will remove the special characters and replace them with spaces. ///
- public interface ILogLineXmlColumnizer : ILogLineColumnizer - { - #region Public methods - - /// - /// You have to implement this function to provide a configuration for LogExpert's XML reader. - /// - /// - IXmlLogConfiguration GetXmlLogConfiguration(); - - /// - /// Returns the text which should be copied into the clipboard when the user want to copy selected - /// lines to clipboard. - /// - /// The line as retrieved from the internal log reader. This is - /// the result of the XSLT processing with your provided stylesheet. - /// - /// Callback which may be used by the Columnizer - /// A string which is placed into the clipboard - /// - /// This function is intended to convert the representation of a log line produced by XSLT transformation into - /// a format suitable for clipboard. - /// The method can be used in the case that the XSLT transformation result is not very 'human readable'. - ///

- /// An example is the included Log4jXMLColumnizer. It uses special characters to separate the fields. - /// The characters are added while XSLT transformation. The usual Columnizer functions (e.g. SplitLIne()) will - /// use these markers for line splitting. - /// When copying to clipboard, this method will remove the special characters and replace them with spaces. - ///
- ILogLine GetLineTextForClipboard(ILogLine logLine, ILogLineColumnizerCallback callback); + ILogLine GetLineTextForClipboard (ILogLine logLine, ILogLineColumnizerCallback callback); - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/IPreProcessColumnizer.cs b/src/ColumnizerLib/IPreProcessColumnizer.cs index 6c8e9cbd..92a1ea86 100644 --- a/src/ColumnizerLib/IPreProcessColumnizer.cs +++ b/src/ColumnizerLib/IPreProcessColumnizer.cs @@ -2,64 +2,63 @@ using System.Collections.Generic; using System.Text; -namespace LogExpert +namespace LogExpert; + +/// +/// +/// Implement this interface in your columnizer if you want to pre-process every line +/// directly when it's loaded from file system. +/// +/// You can also use this to drop lines. +/// +/// +/// +/// +/// By implementing this interface with your Columnizer you get the ability to modify the +/// content of a log file right before it will be seen by LogExpert. +/// +/// +/// Note that the +/// method is only used when loading a line from disk. Because of internal buffering a log line may +/// be read only once or multiple times. You have to ensure that the behaviour is consistent +/// for every call to for a specific line. That's especially true +/// when dropping lines. Dropping a line changes the line count seen by LogExpert. That has implications +/// for things like bookmarks etc. +/// +/// +public interface IPreProcessColumnizer { + #region Public methods + /// - /// - /// Implement this interface in your columnizer if you want to pre-process every line - /// directly when it's loaded from file system. - /// - /// You can also use this to drop lines. - /// + /// This function is called for every line read from the log file. You can change the content + /// by returning a different string. You can also drop the complete line by returning null. /// + /// Line content + /// Line number as seen by LogExpert + /// Actual line number in the file + /// The changed content or null to drop the line /// /// - /// By implementing this interface with your Columnizer you get the ability to modify the - /// content of a log file right before it will be seen by LogExpert. + /// The values of lineNum and realLineNum differ only if you drop lines (by returning null). + /// When you drop a line, this line is hidden completely from LogExpert's log buffers. No chance + /// to bring it back later. When you drop a line, the lineNum will stay the same for the next + /// method call (for the next line). But realLineNum will increase for every call. + /// + /// + /// A usage example is the CsvColumnizer: If configuration says that there are field names + /// in the first line if the CSV file, the CsvColumnizer will store the first line for later + /// field name retrieval. But then the line is dropped. So the line isn't seen by LogExpert. + /// Detecting the first line in the file is only possible by checking the realLineNum parameter. /// /// - /// Note that the - /// method is only used when loading a line from disk. Because of internal buffering a log line may - /// be read only once or multiple times. You have to ensure that the behaviour is consistent - /// for every call to for a specific line. That's especially true - /// when dropping lines. Dropping a line changes the line count seen by LogExpert. That has implications - /// for things like bookmarks etc. + /// Remember that the method is called in an early state + /// when loading the file. So the file isn't loaded completely and the internal state + /// of LogExpert isn't complete. You cannot make any assumptions about file size or other + /// things. The given parameters are the only 'stateful' informations you can rely on. /// /// - public interface IPreProcessColumnizer - { - #region Public methods - - /// - /// This function is called for every line read from the log file. You can change the content - /// by returning a different string. You can also drop the complete line by returning null. - /// - /// Line content - /// Line number as seen by LogExpert - /// Actual line number in the file - /// The changed content or null to drop the line - /// - /// - /// The values of lineNum and realLineNum differ only if you drop lines (by returning null). - /// When you drop a line, this line is hidden completely from LogExpert's log buffers. No chance - /// to bring it back later. When you drop a line, the lineNum will stay the same for the next - /// method call (for the next line). But realLineNum will increase for every call. - /// - /// - /// A usage example is the CsvColumnizer: If configuration says that there are field names - /// in the first line if the CSV file, the CsvColumnizer will store the first line for later - /// field name retrieval. But then the line is dropped. So the line isn't seen by LogExpert. - /// Detecting the first line in the file is only possible by checking the realLineNum parameter. - /// - /// - /// Remember that the method is called in an early state - /// when loading the file. So the file isn't loaded completely and the internal state - /// of LogExpert isn't complete. You cannot make any assumptions about file size or other - /// things. The given parameters are the only 'stateful' informations you can rely on. - /// - /// - string PreProcessLine(string logLine, int lineNum, int realLineNum); + string PreProcessLine(string logLine, int lineNum, int realLineNum); - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/ITextValue.cs b/src/ColumnizerLib/ITextValue.cs index bc6a218c..80b36fe9 100644 --- a/src/ColumnizerLib/ITextValue.cs +++ b/src/ColumnizerLib/ITextValue.cs @@ -1,11 +1,10 @@ -namespace LogExpert +namespace LogExpert; + +public interface ITextValue { - public interface ITextValue - { - #region Properties + #region Properties - string Text { get; } + string Text { get; } - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/IXmlLogConfiguration.cs b/src/ColumnizerLib/IXmlLogConfiguration.cs index b88419b8..c48d7535 100644 --- a/src/ColumnizerLib/IXmlLogConfiguration.cs +++ b/src/ColumnizerLib/IXmlLogConfiguration.cs @@ -1,37 +1,36 @@ -namespace LogExpert +namespace LogExpert; + +/// +/// This interface declares the configuration data which is needed for XML log file parsing. +/// +public interface IXmlLogConfiguration { + #region Properties + /// - /// This interface declares the configuration data which is needed for XML log file parsing. + /// The opening XML tag for a log entry. Every log entry starts with this tag.

+ /// Example: <log4j:event> ///
- public interface IXmlLogConfiguration - { - #region Properties - - /// - /// The opening XML tag for a log entry. Every log entry starts with this tag.

- /// Example: <log4j:event> - ///
- string XmlStartTag { get; } + string XmlStartTag { get; } - /// - /// The closing tag for a log entry.

- /// Example: </log4j:event> - ///
- string XmlEndTag { get; } + /// + /// The closing tag for a log entry.

+ /// Example: </log4j:event> + ///
+ string XmlEndTag { get; } - /// - /// A complete XSLT which is used to transform the XML fragments into text lines which can be - /// processed by the Columnizer. - /// - string Stylesheet { get; } + /// + /// A complete XSLT which is used to transform the XML fragments into text lines which can be + /// processed by the Columnizer. + /// + string Stylesheet { get; } - /// - /// A namespace declaration. The returned array must contain 2 strings: The namespace and its declaration.

- /// Example: {"log4j", "http://jakarta.apache.org/log4j"} - /// - ///
- string[] Namespace { get; } + /// + /// A namespace declaration. The returned array must contain 2 strings: The namespace and its declaration.

+ /// Example: {"log4j", "http://jakarta.apache.org/log4j"} + /// + ///
+ string[] Namespace { get; } - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/ColumnizerLib/LineEntry.cs b/src/ColumnizerLib/LineEntry.cs index c0f02c17..bcbb4699 100644 --- a/src/ColumnizerLib/LineEntry.cs +++ b/src/ColumnizerLib/LineEntry.cs @@ -1,20 +1,19 @@ -namespace LogExpert +namespace LogExpert; + +/// +/// This helper struct holds a log line and its line number (zero based). +/// This struct is used by . +/// +/// +public struct LineEntry { /// - /// This helper struct holds a log line and its line number (zero based). - /// This struct is used by . + /// The content of the line. /// - /// - public struct LineEntry - { - /// - /// The content of the line. - /// - public ILogLine logLine; + public ILogLine logLine; - /// - /// The line number. See for an explanation of the line number. - /// - public int lineNum; - } + /// + /// The line number. See for an explanation of the line number. + /// + public int lineNum; } \ No newline at end of file diff --git a/src/ColumnizerLib/Priority.cs b/src/ColumnizerLib/Priority.cs index de968b24..964820aa 100644 --- a/src/ColumnizerLib/Priority.cs +++ b/src/ColumnizerLib/Priority.cs @@ -1,33 +1,32 @@ -namespace LogExpert +namespace LogExpert; + +/// +/// Priority for columnizer. +/// +public enum Priority { /// - /// Priority for columnizer. + /// Not support target file. /// - public enum Priority - { - /// - /// Not support target file. - /// - NotSupport = 0, + NotSupport = 0, - /// - /// Can support target file. E.g. default one CanSupport most of the files. - /// - CanSupport, + /// + /// Can support target file. E.g. default one CanSupport most of the files. + /// + CanSupport, - /// - /// Target file is soundly supported. E.g. JsonColumnizer WellSupport all json files. - /// - WellSupport, + /// + /// Target file is soundly supported. E.g. JsonColumnizer WellSupport all json files. + /// + WellSupport, - /// - /// The columnizer is designed to support target file. E.g. JsonCompactColumnizer PerfectlySupport all compact Json files. - /// - PerfectlySupport, + /// + /// The columnizer is designed to support target file. E.g. JsonCompactColumnizer PerfectlySupport all compact Json files. + /// + PerfectlySupport, - /// - /// Target file is only supported by this columnizer. - /// - Exclusive - } + /// + /// Target file is only supported by this columnizer. + /// + Exclusive } \ No newline at end of file diff --git a/src/CsvColumnizer/CsvColumn.cs b/src/CsvColumnizer/CsvColumn.cs index 4b209a5c..c899c940 100644 --- a/src/CsvColumnizer/CsvColumn.cs +++ b/src/CsvColumnizer/CsvColumn.cs @@ -1,11 +1,10 @@ -namespace CsvColumnizer +namespace CsvColumnizer; + +internal class CsvColumn(string name) { - internal class CsvColumn(string name) - { - #region Properties + #region Properties - public string Name { get; } = name; + public string Name { get; } = name; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/CsvColumnizer/CsvColumnizer.cs b/src/CsvColumnizer/CsvColumnizer.cs index 3f5491bc..8d6bffe5 100644 --- a/src/CsvColumnizer/CsvColumnizer.cs +++ b/src/CsvColumnizer/CsvColumnizer.cs @@ -13,277 +13,276 @@ using System.Windows.Forms; [assembly: SupportedOSPlatform("windows")] -namespace CsvColumnizer +namespace CsvColumnizer; + +/// +/// This Columnizer can parse CSV files. It uses the IInitColumnizer interface for support of dynamic field count. +/// The IPreProcessColumnizer is implemented to read field names from the very first line of the file. Then +/// the line is dropped. So it's not seen by LogExpert. The field names will be used as column names. +/// +public class CsvColumnizer : ILogLineColumnizer, IInitColumnizer, IColumnizerConfigurator, IPreProcessColumnizer, IColumnizerPriority { - /// - /// This Columnizer can parse CSV files. It uses the IInitColumnizer interface for support of dynamic field count. - /// The IPreProcessColumnizer is implemented to read field names from the very first line of the file. Then - /// the line is dropped. So it's not seen by LogExpert. The field names will be used as column names. - /// - public class CsvColumnizer : ILogLineColumnizer, IInitColumnizer, IColumnizerConfigurator, IPreProcessColumnizer, IColumnizerPriority - { - #region Fields + #region Fields - private static readonly string _configFileName = "csvcolumnizer.json"; + private static readonly string _configFileName = "csvcolumnizer.json"; - private readonly IList _columnList = []; - private CsvColumnizerConfig _config; + private readonly IList _columnList = []; + private CsvColumnizerConfig _config; - private ILogLine _firstLine; + private ILogLine _firstLine; - // if CSV is detected to be 'invalid' the columnizer will behave like a default columnizer - private bool _isValidCsv; + // if CSV is detected to be 'invalid' the columnizer will behave like a default columnizer + private bool _isValidCsv; - #endregion + #endregion - #region Public methods + #region Public methods - public string PreProcessLine(string logLine, int lineNum, int realLineNum) + public string PreProcessLine(string logLine, int lineNum, int realLineNum) + { + if (realLineNum == 0) { - if (realLineNum == 0) - { - // store for later field names and field count retrieval - _firstLine = new CsvLogLine(logLine, 0); + // store for later field names and field count retrieval + _firstLine = new CsvLogLine(logLine, 0); - if (_config.MinColumns > 0) + if (_config.MinColumns > 0) + { + using CsvReader csv = new(new StringReader(logLine), _config.ReaderConfiguration); + if (csv.Parser.Count < _config.MinColumns) { - using CsvReader csv = new(new StringReader(logLine), _config.ReaderConfiguration); - if (csv.Parser.Count < _config.MinColumns) - { - // on invalid CSV don't hide the first line from LogExpert, since the file will be displayed in plain mode - _isValidCsv = false; - return logLine; - } + // on invalid CSV don't hide the first line from LogExpert, since the file will be displayed in plain mode + _isValidCsv = false; + return logLine; } - - _isValidCsv = true; } - if (_config.HasFieldNames && realLineNum == 0) - { - return null; // hide from LogExpert - } - - if (_config.CommentChar != ' ' && logLine.StartsWith("" + _config.CommentChar)) - { - return null; - } - - return logLine; + _isValidCsv = true; } - public string GetName() + if (_config.HasFieldNames && realLineNum == 0) { - return "CSV Columnizer"; + return null; // hide from LogExpert } - public string GetDescription() + if (_config.CommentChar != ' ' && logLine.StartsWith("" + _config.CommentChar)) { - return "Splits CSV files into columns.\r\n\r\nCredits:\r\nThis Columnizer uses the CsvHelper. https://github.com/JoshClose/CsvHelper. \r\n"; + return null; } - public int GetColumnCount() - { - return _isValidCsv ? _columnList.Count : 1; - } + return logLine; + } - public string[] GetColumnNames() - { - string[] names = new string[GetColumnCount()]; - if (_isValidCsv) - { - int i = 0; - foreach (CsvColumn column in _columnList) - { - names[i++] = column.Name; - } - } - else - { - names[0] = "Text"; - } + public string GetName() + { + return "CSV Columnizer"; + } - return names; - } + public string GetDescription() + { + return "Splits CSV files into columns.\r\n\r\nCredits:\r\nThis Columnizer uses the CsvHelper. https://github.com/JoshClose/CsvHelper. \r\n"; + } + + public int GetColumnCount() + { + return _isValidCsv ? _columnList.Count : 1; + } - public IColumnizedLogLine SplitLine(ILogLineColumnizerCallback callback, ILogLine line) + public string[] GetColumnNames() + { + var names = new string[GetColumnCount()]; + if (_isValidCsv) { - if (_isValidCsv) + var i = 0; + foreach (CsvColumn column in _columnList) { - return SplitCsvLine(line); + names[i++] = column.Name; } - - return CreateColumnizedLogLine(line); } - - private static ColumnizedLogLine CreateColumnizedLogLine(ILogLine line) + else { - ColumnizedLogLine cLogLine = new() - { - LogLine = line - }; - cLogLine.ColumnValues = [new Column { FullValue = line.FullLine, Parent = cLogLine }]; - return cLogLine; + names[0] = "Text"; } - public bool IsTimeshiftImplemented() - { - return false; - } + return names; + } - public void SetTimeOffset(int msecOffset) + public IColumnizedLogLine SplitLine(ILogLineColumnizerCallback callback, ILogLine line) + { + if (_isValidCsv) { - throw new NotImplementedException(); + return SplitCsvLine(line); } - public int GetTimeOffset() - { - throw new NotImplementedException(); - } + return CreateColumnizedLogLine(line); + } - public DateTime GetTimestamp(ILogLineColumnizerCallback callback, ILogLine line) + private static ColumnizedLogLine CreateColumnizedLogLine(ILogLine line) + { + ColumnizedLogLine cLogLine = new() { - throw new NotImplementedException(); - } + LogLine = line + }; + cLogLine.ColumnValues = [new Column { FullValue = line.FullLine, Parent = cLogLine }]; + return cLogLine; + } - public void PushValue(ILogLineColumnizerCallback callback, int column, string value, string oldValue) - { - throw new NotImplementedException(); - } + public bool IsTimeshiftImplemented() + { + return false; + } + + public void SetTimeOffset(int msecOffset) + { + throw new NotImplementedException(); + } + + public int GetTimeOffset() + { + throw new NotImplementedException(); + } + + public DateTime GetTimestamp(ILogLineColumnizerCallback callback, ILogLine line) + { + throw new NotImplementedException(); + } - public void Selected(ILogLineColumnizerCallback callback) + public void PushValue(ILogLineColumnizerCallback callback, int column, string value, string oldValue) + { + throw new NotImplementedException(); + } + + public void Selected(ILogLineColumnizerCallback callback) + { + if (_isValidCsv) // see PreProcessLine() { - if (_isValidCsv) // see PreProcessLine() - { - _columnList.Clear(); - ILogLine line = _config.HasFieldNames ? _firstLine : callback.GetLogLine(0); + _columnList.Clear(); + ILogLine line = _config.HasFieldNames ? _firstLine : callback.GetLogLine(0); - if (line != null) - { - using CsvReader csv = new(new StringReader(line.FullLine), _config.ReaderConfiguration); - csv.Read(); - csv.ReadHeader(); + if (line != null) + { + using CsvReader csv = new(new StringReader(line.FullLine), _config.ReaderConfiguration); + csv.Read(); + csv.ReadHeader(); - int fieldCount = csv.Parser.Count; + var fieldCount = csv.Parser.Count; - string[] headerRecord = csv.HeaderRecord; + var headerRecord = csv.HeaderRecord; - if (_config.HasFieldNames && headerRecord != null) + if (_config.HasFieldNames && headerRecord != null) + { + foreach (var headerColumn in headerRecord) { - foreach (string headerColumn in headerRecord) - { - _columnList.Add(new CsvColumn(headerColumn)); - } + _columnList.Add(new CsvColumn(headerColumn)); } - else + } + else + { + for (var i = 0; i < fieldCount; ++i) { - for (int i = 0; i < fieldCount; ++i) - { - _columnList.Add(new CsvColumn("Column " + i + 1)); - } + _columnList.Add(new CsvColumn("Column " + i + 1)); } } } } + } - public void DeSelected(ILogLineColumnizerCallback callback) - { - // nothing to do - } + public void DeSelected(ILogLineColumnizerCallback callback) + { + // nothing to do + } - public void Configure(ILogLineColumnizerCallback callback, string configDir) - { - string configPath = configDir + "\\" + _configFileName; - FileInfo fileInfo = new(configPath); + public void Configure(ILogLineColumnizerCallback callback, string configDir) + { + var configPath = configDir + "\\" + _configFileName; + FileInfo fileInfo = new(configPath); - CsvColumnizerConfigDlg dlg = new(_config); + CsvColumnizerConfigDlg dlg = new(_config); - if (dlg.ShowDialog() == DialogResult.OK) - { - _config.VersionBuild = Assembly.GetExecutingAssembly().GetName().Version.Build; + if (dlg.ShowDialog() == DialogResult.OK) + { + _config.VersionBuild = Assembly.GetExecutingAssembly().GetName().Version.Build; - using (StreamWriter sw = new(fileInfo.Create())) - { - JsonSerializer serializer = new(); - serializer.Serialize(sw, _config); - } + using (StreamWriter sw = new(fileInfo.Create())) + { + JsonSerializer serializer = new(); + serializer.Serialize(sw, _config); + } - _config.ConfigureReaderConfiguration(); + _config.ConfigureReaderConfiguration(); - Selected(callback); - } + Selected(callback); } + } - public void LoadConfig(string configDir) - { - string configPath = Path.Combine(configDir, _configFileName); + public void LoadConfig(string configDir) + { + var configPath = Path.Combine(configDir, _configFileName); - if (!File.Exists(configPath)) + if (!File.Exists(configPath)) + { + _config = new CsvColumnizerConfig(); + _config.InitDefaults(); + } + else + { + try { - _config = new CsvColumnizerConfig(); - _config.InitDefaults(); + _config = JsonConvert.DeserializeObject(File.ReadAllText(configPath)); + _config.ConfigureReaderConfiguration(); } - else + catch (Exception e) { - try - { - _config = JsonConvert.DeserializeObject(File.ReadAllText(configPath)); - _config.ConfigureReaderConfiguration(); - } - catch (Exception e) - { - MessageBox.Show($"Error while deserializing config data: {e.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - _config = new CsvColumnizerConfig(); - _config.InitDefaults(); - } + MessageBox.Show($"Error while deserializing config data: {e.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + _config = new CsvColumnizerConfig(); + _config.InitDefaults(); } } + } - public Priority GetPriority(string fileName, IEnumerable samples) - { - Priority result = Priority.NotSupport; - - if (fileName.EndsWith("csv", StringComparison.OrdinalIgnoreCase)) - { - result = Priority.CanSupport; - } + public Priority GetPriority(string fileName, IEnumerable samples) + { + Priority result = Priority.NotSupport; - return result; + if (fileName.EndsWith("csv", StringComparison.OrdinalIgnoreCase)) + { + result = Priority.CanSupport; } - #endregion + return result; + } - #region Private Methods + #endregion - private IColumnizedLogLine SplitCsvLine(ILogLine line) - { - ColumnizedLogLine cLogLine = new() - { - LogLine = line - }; + #region Private Methods - using CsvReader csv = new(new StringReader(line.FullLine), _config.ReaderConfiguration); - csv.Read(); - csv.ReadHeader(); + private IColumnizedLogLine SplitCsvLine(ILogLine line) + { + ColumnizedLogLine cLogLine = new() + { + LogLine = line + }; - //we only read line by line and not the whole file so it is always the header - string[] records = csv.HeaderRecord; + using CsvReader csv = new(new StringReader(line.FullLine), _config.ReaderConfiguration); + csv.Read(); + csv.ReadHeader(); - if (records != null) - { - List columns = []; + //we only read line by line and not the whole file so it is always the header + var records = csv.HeaderRecord; - foreach (string record in records) - { - columns.Add(new Column { FullValue = record, Parent = cLogLine }); - } + if (records != null) + { + List columns = []; - cLogLine.ColumnValues = columns.Select(a => a as IColumn).ToArray(); + foreach (var record in records) + { + columns.Add(new Column { FullValue = record, Parent = cLogLine }); } - return cLogLine; + cLogLine.ColumnValues = columns.Select(a => a as IColumn).ToArray(); } - #endregion + return cLogLine; } + + #endregion } \ No newline at end of file diff --git a/src/CsvColumnizer/CsvColumnizerConfig.cs b/src/CsvColumnizer/CsvColumnizerConfig.cs index f9b04908..e2841bcf 100644 --- a/src/CsvColumnizer/CsvColumnizerConfig.cs +++ b/src/CsvColumnizer/CsvColumnizerConfig.cs @@ -5,66 +5,65 @@ using System; using System.Globalization; -namespace CsvColumnizer +namespace CsvColumnizer; + +[Serializable] +public class CsvColumnizerConfig { - [Serializable] - public class CsvColumnizerConfig - { - #region Fields + #region Fields - public char CommentChar { get; set; } + public char CommentChar { get; set; } - public string DelimiterChar { get; set; } + public string DelimiterChar { get; set; } - public char EscapeChar { get; set; } + public char EscapeChar { get; set; } - public bool HasFieldNames { get; set; } + public bool HasFieldNames { get; set; } - public int MinColumns { get; set; } + public int MinColumns { get; set; } - public char QuoteChar { get; set; } + public char QuoteChar { get; set; } - public int VersionBuild { get; set; } + public int VersionBuild { get; set; } - [JsonIgnore] - public IReaderConfiguration ReaderConfiguration { get; set; } + [JsonIgnore] + public IReaderConfiguration ReaderConfiguration { get; set; } - #endregion + #endregion - #region Public methods + #region Public methods - public void InitDefaults() + public void InitDefaults() + { + ReaderConfiguration = new CsvConfiguration(CultureInfo.InvariantCulture) { - ReaderConfiguration = new CsvConfiguration(CultureInfo.InvariantCulture) - { - Delimiter = ";", - Escape = '"', - Quote = '"', - Comment = '#', - HasHeaderRecord = true, - TrimOptions = TrimOptions.None - }; - - DelimiterChar = ReaderConfiguration.Delimiter; - EscapeChar = ReaderConfiguration.Escape; - QuoteChar = ReaderConfiguration.Quote; - CommentChar = ReaderConfiguration.Comment; - HasFieldNames = ReaderConfiguration.HasHeaderRecord; - MinColumns = 0; - } - - public void ConfigureReaderConfiguration() + Delimiter = ";", + Escape = '"', + Quote = '"', + Comment = '#', + HasHeaderRecord = true, + TrimOptions = TrimOptions.None + }; + + DelimiterChar = ReaderConfiguration.Delimiter; + EscapeChar = ReaderConfiguration.Escape; + QuoteChar = ReaderConfiguration.Quote; + CommentChar = ReaderConfiguration.Comment; + HasFieldNames = ReaderConfiguration.HasHeaderRecord; + MinColumns = 0; + } + + public void ConfigureReaderConfiguration() + { + ReaderConfiguration = new CsvConfiguration(CultureInfo.InvariantCulture) { - ReaderConfiguration = new CsvConfiguration(CultureInfo.InvariantCulture) - { - Delimiter = DelimiterChar, - Escape = EscapeChar, - Quote = QuoteChar, - Comment = CommentChar, - HasHeaderRecord = HasFieldNames - }; - } - - #endregion + Delimiter = DelimiterChar, + Escape = EscapeChar, + Quote = QuoteChar, + Comment = CommentChar, + HasHeaderRecord = HasFieldNames + }; } + + #endregion } \ No newline at end of file diff --git a/src/CsvColumnizer/CsvColumnizerConfigDlg.cs b/src/CsvColumnizer/CsvColumnizerConfigDlg.cs index 4c2fd0ab..61d421f9 100644 --- a/src/CsvColumnizer/CsvColumnizerConfigDlg.cs +++ b/src/CsvColumnizer/CsvColumnizerConfigDlg.cs @@ -2,71 +2,70 @@ using System.Drawing; using System.Windows.Forms; -namespace CsvColumnizer -{ - public partial class CsvColumnizerConfigDlg : Form - { - #region Fields +namespace CsvColumnizer; - private readonly CsvColumnizerConfig _config; +public partial class CsvColumnizerConfigDlg : Form +{ + #region Fields - #endregion + private readonly CsvColumnizerConfig _config; - #region cTor + #endregion - public CsvColumnizerConfigDlg(CsvColumnizerConfig config) - { - SuspendLayout(); - AutoScaleDimensions = new SizeF(96F, 96F); - AutoScaleMode = AutoScaleMode.Dpi; + #region cTor - _config = config; - InitializeComponent(); - FillValues(); - ResumeLayout(); - } + public CsvColumnizerConfigDlg(CsvColumnizerConfig config) + { + SuspendLayout(); + AutoScaleDimensions = new SizeF(96F, 96F); + AutoScaleMode = AutoScaleMode.Dpi; + + _config = config; + InitializeComponent(); + FillValues(); + ResumeLayout(); + } - #endregion + #endregion - #region Private Methods + #region Private Methods - private void FillValues() - { - delimiterTextBox.Text = _config.DelimiterChar; - textBoxQuoteChar.Text = _config.QuoteChar.ToString(); - textboxEscapeChar.Text = _config.EscapeChar.ToString(); - checkBoxEscape.Checked = _config.EscapeChar != '\0'; - textBoxCommentChar.Text = _config.CommentChar.ToString(); - checkBoxFieldNames.Checked = _config.HasFieldNames; - textboxEscapeChar.Enabled = checkBoxEscape.Checked; - numericUpDownMinColumns.Value = _config.MinColumns; - } + private void FillValues() + { + delimiterTextBox.Text = _config.DelimiterChar; + textBoxQuoteChar.Text = _config.QuoteChar.ToString(); + textboxEscapeChar.Text = _config.EscapeChar.ToString(); + checkBoxEscape.Checked = _config.EscapeChar != '\0'; + textBoxCommentChar.Text = _config.CommentChar.ToString(); + checkBoxFieldNames.Checked = _config.HasFieldNames; + textboxEscapeChar.Enabled = checkBoxEscape.Checked; + numericUpDownMinColumns.Value = _config.MinColumns; + } - private void RetrieveValues() - { - _config.DelimiterChar = delimiterTextBox.Text; - _config.QuoteChar = textBoxQuoteChar.Text[0]; - _config.EscapeChar = checkBoxEscape.Checked ? textboxEscapeChar.Text[0] : '\0'; - _config.CommentChar = textBoxCommentChar.Text[0]; - _config.HasFieldNames = checkBoxFieldNames.Checked; - _config.MinColumns = (int)numericUpDownMinColumns.Value; - } + private void RetrieveValues() + { + _config.DelimiterChar = delimiterTextBox.Text; + _config.QuoteChar = textBoxQuoteChar.Text[0]; + _config.EscapeChar = checkBoxEscape.Checked ? textboxEscapeChar.Text[0] : '\0'; + _config.CommentChar = textBoxCommentChar.Text[0]; + _config.HasFieldNames = checkBoxFieldNames.Checked; + _config.MinColumns = (int)numericUpDownMinColumns.Value; + } - #endregion + #endregion - #region Events handler + #region Events handler - private void OnOkButtonClick(object sender, EventArgs e) - { - RetrieveValues(); - } + private void OnOkButtonClick(object sender, EventArgs e) + { + RetrieveValues(); + } - private void OnEscapeCheckBoxCheckedChanged(object sender, EventArgs e) - { - textboxEscapeChar.Enabled = checkBoxEscape.Checked; - } + private void OnEscapeCheckBoxCheckedChanged(object sender, EventArgs e) + { + textboxEscapeChar.Enabled = checkBoxEscape.Checked; + } - #endregion + #endregion - } } \ No newline at end of file diff --git a/src/CsvColumnizer/CsvLogLine.cs b/src/CsvColumnizer/CsvLogLine.cs index 6fdef11d..8187a496 100644 --- a/src/CsvColumnizer/CsvLogLine.cs +++ b/src/CsvColumnizer/CsvLogLine.cs @@ -1,17 +1,16 @@ using LogExpert; -namespace CsvColumnizer +namespace CsvColumnizer; + +public class CsvLogLine(string fullLine, int lineNumber) : ILogLine { - public class CsvLogLine(string fullLine, int lineNumber) : ILogLine - { - #region Properties + #region Properties - public string FullLine { get; set; } = fullLine; + public string FullLine { get; set; } = fullLine; - public int LineNumber { get; set; } = lineNumber; + public int LineNumber { get; set; } = lineNumber; - string ITextValue.Text => FullLine; + string ITextValue.Text => FullLine; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/DefaultPlugins/ProcessLauncher.cs b/src/DefaultPlugins/ProcessLauncher.cs index 7d0ce891..8e381867 100644 --- a/src/DefaultPlugins/ProcessLauncher.cs +++ b/src/DefaultPlugins/ProcessLauncher.cs @@ -1,80 +1,78 @@ -using System.Diagnostics; +using System.Diagnostics; -namespace LogExpert +namespace LogExpert; + +internal class ProcessLauncher : IKeywordAction { - //TODO: Not in use - internal class ProcessLauncher : IKeywordAction - { - #region Properties + #region Properties - public string Text => GetName(); + public string Text => GetName(); - #endregion + #endregion - #region IKeywordAction Member + #region IKeywordAction Member - private readonly object _callbackLock = new object(); + private readonly object _callbackLock = new(); + + public void Execute (string keyword, string param, ILogExpertCallback callback, ILogLineColumnizer columnizer) + { + var start = 0; + int end; - public void Execute(string keyword, string param, ILogExpertCallback callback, ILogLineColumnizer columnizer) + if (param.StartsWith('"')) { - int start = 0; - int end = 0; - - if (param.StartsWith('"')) - { - start = 1; - end = param.IndexOf('"', start); - } - else - { - end = param.IndexOf(' '); - } - - if (end == -1) - { - end = param.Length; - } - - string procName = param[start..end]; - - lock (_callbackLock) - { - string parameters = param[end..].Trim(); - parameters = parameters.Replace("%F", callback.GetFileName()); - parameters = parameters.Replace("%K", keyword); - - int lineNumber = callback.GetLineNum(); //Line Numbers start at 0, but are displayed (+1) - string logline = callback.GetLogLine(lineNumber).FullLine; - parameters = parameters.Replace("%L", string.Empty + lineNumber); - parameters = parameters.Replace("%T", callback.GetTabTitle()); - parameters = parameters.Replace("%C", logline); - - Process explorer = new(); - explorer.StartInfo.FileName = procName; - explorer.StartInfo.Arguments = parameters; - explorer.StartInfo.UseShellExecute = false; - explorer.Start(); - } + start = 1; + end = param.IndexOf('"', start); + } + else + { + end = param.IndexOf(' '); } - public string GetName() + if (end == -1) { - return "ProcessLauncher keyword plugin"; + end = param.Length; } + var procName = param[start..end]; - public string GetDescription() + lock (_callbackLock) { - return "Launches an external process. The plugin's parameter is the process name " + - "and its (optional) command line.\r\n" + - "Use the following variables for command line replacements:\r\n" + - "%F = Log file name (full path)\r\n" + - "%T = Tab title\r\n" + - "%L = Line number of keyword hit\r\n" + - "%K = Keyword\r\n" + - "%C = Complete line content"; + var parameters = param[end..].Trim(); + parameters = parameters.Replace("%F", callback.GetFileName()); + parameters = parameters.Replace("%K", keyword); + + var lineNumber = callback.GetLineNum(); //Line Numbers start at 0, but are displayed (+1) + var logline = callback.GetLogLine(lineNumber).FullLine; + parameters = parameters.Replace("%L", string.Empty + lineNumber); + parameters = parameters.Replace("%T", callback.GetTabTitle()); + parameters = parameters.Replace("%C", logline); + + Process explorer = new(); + explorer.StartInfo.FileName = procName; + explorer.StartInfo.Arguments = parameters; + explorer.StartInfo.UseShellExecute = false; + explorer.Start(); } + } - #endregion + public string GetName () + { + return "ProcessLauncher keyword plugin"; + } + + + public string GetDescription () + { + return "Launches an external process. The plugin's parameter is the process name " + + "and its (optional) command line.\r\n" + + "Use the following variables for command line replacements:\r\n" + + "%F = Log file name (full path)\r\n" + + "%T = Tab title\r\n" + + "%L = Line number of keyword hit\r\n" + + "%K = Keyword\r\n" + + "%C = Complete line content"; } + + #endregion } \ No newline at end of file diff --git a/src/FlashIconHighlighter/FlashIconPlugin.cs b/src/FlashIconHighlighter/FlashIconPlugin.cs index 3e4b0341..fdf4e2f3 100644 --- a/src/FlashIconHighlighter/FlashIconPlugin.cs +++ b/src/FlashIconHighlighter/FlashIconPlugin.cs @@ -1,61 +1,57 @@ -using LogExpert; - using System; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Windows.Forms; +using LogExpert; + [assembly: SupportedOSPlatform("windows")] -namespace FlashIconHighlighter +namespace FlashIconHighlighter; + +internal class FlashIconPlugin : IKeywordAction { - internal class FlashIconPlugin : IKeywordAction - { - #region Properties + #region Properties - public string Text - { - get { return GetName(); } - } + public string Text => GetName(); - #endregion + #endregion - #region IKeywordAction Member + #region IKeywordAction Member - public void Execute(string keyword, string param, ILogExpertCallback callback, ILogLineColumnizer columnizer) + public void Execute (string keyword, string param, ILogExpertCallback callback, ILogLineColumnizer columnizer) + { + FormCollection openForms = Application.OpenForms; + foreach (Form form in openForms) { - FormCollection openForms = Application.OpenForms; - foreach (Form form in openForms) + if (form.TopLevel && form.Name.Equals("LogTabWindow", StringComparison.OrdinalIgnoreCase) && form.Text.Contains(callback.GetFileName(), StringComparison.Ordinal)) { - if (form.TopLevel && form.Name.Equals("LogTabWindow") && form.Text.Contains(callback.GetFileName())) - { - form.BeginInvoke(FlashWindow, [form]); - } + form.BeginInvoke(FlashWindow, [form]); } } + } - private void FlashWindow(Form form) + private void FlashWindow (Form form) + { + FLASHWINFO fw = new() { - FLASHWINFO fw = new() - { - cbSize = Convert.ToUInt32(Marshal.SizeOf(typeof(FLASHWINFO))), - hwnd = form.Handle, - dwFlags = 14, - uCount = 0 - }; + cbSize = Convert.ToUInt32(Marshal.SizeOf(typeof(FLASHWINFO))), + hwnd = form.Handle, + dwFlags = 14, + uCount = 0 + }; - Win32Stuff.FlashWindowEx(ref fw); - } - - public string GetDescription() - { - return "Let the taskbar icon flash "; - } + Win32Stuff.FlashWindowEx(ref fw); + } - public string GetName() - { - return "Flash Icon"; - } + public string GetDescription () + { + return "Let the taskbar icon flash "; + } - #endregion + public string GetName () + { + return "Flash Icon"; } + + #endregion } \ No newline at end of file diff --git a/src/FlashIconHighlighter/Win32Stuff.cs b/src/FlashIconHighlighter/Win32Stuff.cs index fbb008f3..bc68f3c0 100644 --- a/src/FlashIconHighlighter/Win32Stuff.cs +++ b/src/FlashIconHighlighter/Win32Stuff.cs @@ -1,29 +1,28 @@ using System; using System.Runtime.InteropServices; -namespace FlashIconHighlighter -{ - /* - * Flash stuff stolen from http://blogs.x2line.com/al/archive/2008/04/19/3392.aspx - */ +namespace FlashIconHighlighter; + +/* + * Flash stuff stolen from http://blogs.x2line.com/al/archive/2008/04/19/3392.aspx + */ - [StructLayout(LayoutKind.Sequential)] - public struct FLASHWINFO - { - public uint cbSize; - public IntPtr hwnd; - public int dwFlags; - public uint uCount; - public int dwTimeout; - } +[StructLayout(LayoutKind.Sequential)] +public struct FLASHWINFO +{ + public uint cbSize; + public IntPtr hwnd; + public int dwFlags; + public uint uCount; + public int dwTimeout; +} - public partial class Win32Stuff - { - #region Public methods +public partial class Win32Stuff +{ + #region Public methods - [LibraryImport("user32.dll")] - public static partial int FlashWindowEx(ref FLASHWINFO pwfi); + [LibraryImport("user32.dll")] + public static partial int FlashWindowEx(ref FLASHWINFO pwfi); - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/GlassfishColumnizer/GlassFishLogLine.cs b/src/GlassfishColumnizer/GlassFishLogLine.cs index 4d12c799..284b4073 100644 --- a/src/GlassfishColumnizer/GlassFishLogLine.cs +++ b/src/GlassfishColumnizer/GlassFishLogLine.cs @@ -1,17 +1,16 @@ using LogExpert; -namespace GlassfishColumnizer +namespace GlassfishColumnizer; + +internal class GlassFishLogLine : ILogLine { - internal class GlassFishLogLine : ILogLine - { - #region Properties + #region Properties - public string FullLine { get; set; } + public string FullLine { get; set; } - public int LineNumber { get; set; } + public int LineNumber { get; set; } - string ITextValue.Text => FullLine; + string ITextValue.Text => FullLine; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/GlassfishColumnizer/GlassfishColumnizer.cs b/src/GlassfishColumnizer/GlassfishColumnizer.cs index f5f93951..d80cc0c9 100644 --- a/src/GlassfishColumnizer/GlassfishColumnizer.cs +++ b/src/GlassfishColumnizer/GlassfishColumnizer.cs @@ -1,215 +1,215 @@ -using LogExpert; - using System; using System.Globalization; using System.Linq; -namespace GlassfishColumnizer +using LogExpert; + +namespace GlassfishColumnizer; + +internal class GlassfishColumnizer : ILogLineXmlColumnizer { - internal class GlassfishColumnizer : ILogLineXmlColumnizer - { - #region Fields + #region Fields - public const int COLUMN_COUNT = 2; - protected const string DATETIME_FORMAT = "yyyy-MM-ddTHH:mm:ss.fffzzzz"; - protected const string DATETIME_FORMAT_OUT = "yyyy-MM-dd HH:mm:ss.fff"; + public const int COLUMN_COUNT = 2; + private const string DATETIME_FORMAT = "yyyy-MM-ddTHH:mm:ss.fffzzzz"; + private const string DATETIME_FORMAT_OUT = "yyyy-MM-dd HH:mm:ss.fff"; + private const char separatorChar = '|'; - private static readonly XmlConfig xmlConfig = new(); - private readonly char separatorChar = '|'; - private readonly char[] trimChars = ['|']; - protected CultureInfo cultureInfo = new("en-US"); - protected int timeOffset = 0; + private static readonly XmlConfig xmlConfig = new(); - #endregion + private readonly char[] trimChars = ['|']; + private readonly CultureInfo cultureInfo = new("en-US"); + private int timeOffset; - #region cTor + #endregion - public GlassfishColumnizer() - { - } + #region cTor - #endregion + public GlassfishColumnizer () + { + } - #region Public methods + #endregion - public IXmlLogConfiguration GetXmlLogConfiguration() - { - return xmlConfig; - } + #region Public methods + + public IXmlLogConfiguration GetXmlLogConfiguration () + { + return xmlConfig; + } - public ILogLine GetLineTextForClipboard(ILogLine logLine, ILogLineColumnizerCallback callback) + public ILogLine GetLineTextForClipboard (ILogLine logLine, ILogLineColumnizerCallback callback) + { + GlassFishLogLine line = new() { - GlassFishLogLine line = new() - { - FullLine = logLine.FullLine.Replace(separatorChar, '|'), - LineNumber = logLine.LineNumber - }; + FullLine = logLine.FullLine.Replace(separatorChar, '|'), + LineNumber = logLine.LineNumber + }; - return line; - } + return line; + } - public string GetName() - { - return "Classfish"; - } + public string GetName () + { + return "Classfish"; + } + + public string GetDescription () + { + return "Parse the timestamps in Glassfish logfiles."; + } + + public int GetColumnCount () + { + return COLUMN_COUNT; + } + + public string[] GetColumnNames () + { + return ["Date/Time", "Message"]; + } + + public IColumnizedLogLine SplitLine (ILogLineColumnizerCallback callback, ILogLine line) + { + ColumnizedLogLine cLogLine = new(); + cLogLine.LogLine = line; - public string GetDescription() + var temp = line.FullLine; + + Column[] columns = Column.CreateColumns(COLUMN_COUNT, cLogLine); + cLogLine.ColumnValues = columns.Select(a => a as IColumn).ToArray(); + + // delete '[#|' and '|#]' + if (temp.StartsWith("[#|")) { - return "Parse the timestamps in Glassfish logfiles."; + temp = temp[3..]; } - public int GetColumnCount() + if (temp.EndsWith("|#]")) { - return COLUMN_COUNT; + temp = temp[..^3]; } - public string[] GetColumnNames() + // If the line is too short (i.e. does not follow the format for this columnizer) return the whole line content + // in colum 8 (the log message column). Date and time column will be left blank. + if (temp.Length < 28) { - return ["Date/Time", "Message"]; + columns[1].FullValue = temp; } - - public IColumnizedLogLine SplitLine(ILogLineColumnizerCallback callback, ILogLine line) + else { - ColumnizedLogLine cLogLine = new(); - cLogLine.LogLine = line; - - string temp = line.FullLine; - - Column[] columns = Column.CreateColumns(COLUMN_COUNT, cLogLine); - cLogLine.ColumnValues = columns.Select(a => a as IColumn).ToArray(); - - // delete '[#|' and '|#]' - if (temp.StartsWith("[#|")) + try { - temp = temp[3..]; - } + DateTime dateTime = GetTimestamp(callback, line); + if (dateTime == DateTime.MinValue) + { + columns[1].FullValue = temp; + } - if (temp.EndsWith("|#]")) + var newDate = dateTime.ToString(DATETIME_FORMAT_OUT); + columns[0].FullValue = newDate; + } + catch (Exception) { - temp = temp[..^3]; + columns[0].FullValue = "n/a"; } - // If the line is too short (i.e. does not follow the format for this columnizer) return the whole line content - // in colum 8 (the log message column). Date and time column will be left blank. - if (temp.Length < 28) + Column timestmp = columns[0]; + + string[] cols; + cols = temp.Split(trimChars, COLUMN_COUNT, StringSplitOptions.None); + + if (cols.Length != COLUMN_COUNT) { + columns[0].FullValue = string.Empty; columns[1].FullValue = temp; } else { - try - { - DateTime dateTime = GetTimestamp(callback, line); - if (dateTime == DateTime.MinValue) - { - columns[1].FullValue = temp; - } - - string newDate = dateTime.ToString(DATETIME_FORMAT_OUT); - columns[0].FullValue = newDate; - } - catch (Exception) - { - columns[0].FullValue = "n/a"; - } + columns[0] = timestmp; + columns[1].FullValue = cols[1]; + } + } - Column timestmp = columns[0]; + return cLogLine; + } - string[] cols; - cols = temp.Split(trimChars, COLUMN_COUNT, StringSplitOptions.None); + public bool IsTimeshiftImplemented () + { + return true; + } - if (cols.Length != COLUMN_COUNT) - { - columns[0].FullValue = string.Empty; - columns[1].FullValue = temp; - } - else - { - columns[0] = timestmp; - columns[1].FullValue = cols[1]; - } - } + public void SetTimeOffset (int msecOffset) + { + timeOffset = msecOffset; + } - return cLogLine; - } + public int GetTimeOffset () + { + return timeOffset; + } + + public DateTime GetTimestamp (ILogLineColumnizerCallback callback, ILogLine logLine) + { + var temp = logLine.FullLine; - public bool IsTimeshiftImplemented() + // delete '[#|' and '|#]' + if (temp.StartsWith("[#|")) { - return true; + temp = temp[3..]; } - public void SetTimeOffset(int msecOffset) + if (temp.EndsWith("|#]")) { - timeOffset = msecOffset; + temp = temp[..^3]; } - public int GetTimeOffset() + if (temp.Length < 28) { - return timeOffset; + return DateTime.MinValue; } - public DateTime GetTimestamp(ILogLineColumnizerCallback callback, ILogLine logLine) + var endIndex = temp.IndexOf(separatorChar, 1); + if (endIndex > 28 || endIndex < 0) { - string temp = logLine.FullLine; - - // delete '[#|' and '|#]' - if (temp.StartsWith("[#|")) - { - temp = temp[3..]; - } - - if (temp.EndsWith("|#]")) - { - temp = temp[..^3]; - } + return DateTime.MinValue; + } - if (temp.Length < 28) - { - return DateTime.MinValue; - } + var value = temp[..endIndex]; - int endIndex = temp.IndexOf(separatorChar, 1); - if (endIndex > 28 || endIndex < 0) + try + { + // convert glassfish timestamp into a readable format: + if (DateTime.TryParseExact(value, DATETIME_FORMAT, cultureInfo, DateTimeStyles.None, out DateTime timestamp)) { - return DateTime.MinValue; + return timestamp.AddMilliseconds(timeOffset); } - string value = temp[..endIndex]; + return DateTime.MinValue; + } + catch (Exception) + { + return DateTime.MinValue; + } + } + public void PushValue (ILogLineColumnizerCallback callback, int column, string value, string oldValue) + { + if (column == 0) + { try { - // convert glassfish timestamp into a readable format: - if (DateTime.TryParseExact(value, DATETIME_FORMAT, cultureInfo, DateTimeStyles.None, out DateTime timestamp)) - { - return timestamp.AddMilliseconds(timeOffset); - } - - return DateTime.MinValue; + var newDateTime = DateTime.ParseExact(value, DATETIME_FORMAT_OUT, cultureInfo); + var oldDateTime = DateTime.ParseExact(oldValue, DATETIME_FORMAT_OUT, cultureInfo); + var mSecsOld = oldDateTime.Ticks / TimeSpan.TicksPerMillisecond; + var mSecsNew = newDateTime.Ticks / TimeSpan.TicksPerMillisecond; + timeOffset = (int)(mSecsNew - mSecsOld); } - catch (Exception) - { - return DateTime.MinValue; - } - } - - public void PushValue(ILogLineColumnizerCallback callback, int column, string value, string oldValue) - { - if (column == 0) + catch (FormatException) { - try - { - DateTime newDateTime = DateTime.ParseExact(value, DATETIME_FORMAT_OUT, cultureInfo); - DateTime oldDateTime = DateTime.ParseExact(oldValue, DATETIME_FORMAT_OUT, cultureInfo); - long mSecsOld = oldDateTime.Ticks / TimeSpan.TicksPerMillisecond; - long mSecsNew = newDateTime.Ticks / TimeSpan.TicksPerMillisecond; - timeOffset = (int)(mSecsNew - mSecsOld); - } - catch (FormatException) - { - } } } - - #endregion } + + #endregion } \ No newline at end of file diff --git a/src/GlassfishColumnizer/XmlConfig.cs b/src/GlassfishColumnizer/XmlConfig.cs index 44ecec47..0d81e05a 100644 --- a/src/GlassfishColumnizer/XmlConfig.cs +++ b/src/GlassfishColumnizer/XmlConfig.cs @@ -1,19 +1,18 @@ using LogExpert; -namespace GlassfishColumnizer +namespace GlassfishColumnizer; + +internal class XmlConfig : IXmlLogConfiguration { - internal class XmlConfig : IXmlLogConfiguration - { - #region Properties + #region Properties - public string XmlStartTag { get; } = "[#|"; + public string XmlStartTag { get; } = "[#|"; - public string XmlEndTag { get; } = "|#]"; + public string XmlEndTag { get; } = "|#]"; - public string Stylesheet { get; } = null; + public string Stylesheet { get; } - public string[] Namespace => null; + public string[] Namespace => null; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/JsonColumnizer/JsonColumn.cs b/src/JsonColumnizer/JsonColumn.cs index 5279533a..5ac9ed9e 100644 --- a/src/JsonColumnizer/JsonColumn.cs +++ b/src/JsonColumnizer/JsonColumn.cs @@ -1,11 +1,10 @@ -namespace JsonColumnizer +namespace JsonColumnizer; + +public class JsonColumn(string name) { - public class JsonColumn(string name) - { - #region Properties + #region Properties - public string Name { get; } = name; + public string Name { get; } = name; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/JsonColumnizer/JsonColumnizer.cs b/src/JsonColumnizer/JsonColumnizer.cs index c77b45d6..04c6f071 100644 --- a/src/JsonColumnizer/JsonColumnizer.cs +++ b/src/JsonColumnizer/JsonColumnizer.cs @@ -7,225 +7,224 @@ using System.Collections.Generic; using System.Linq; -namespace JsonColumnizer +namespace JsonColumnizer; + +/// +/// This Columnizer can parse JSON files. +/// +public class JsonColumnizer : ILogLineColumnizer, IInitColumnizer, IColumnizerPriority { - /// - /// This Columnizer can parse JSON files. - /// - public class JsonColumnizer : ILogLineColumnizer, IInitColumnizer, IColumnizerPriority - { - #region Fields + #region Fields - private static readonly JsonColumn _initialColumn = new JsonColumn("Text"); + private static readonly JsonColumn _initialColumn = new JsonColumn("Text"); - private readonly IList _columnList = new List([InitialColumn]); + private readonly IList _columnList = new List([InitialColumn]); - #endregion + #endregion - #region Properties + #region Properties - public HashSet ColumnSet { get; set; } = []; + public HashSet ColumnSet { get; set; } = []; - protected IList ColumnList => _columnList; + protected IList ColumnList => _columnList; - protected static JsonColumn InitialColumn => _initialColumn; + protected static JsonColumn InitialColumn => _initialColumn; - #endregion + #endregion - #region Public methods + #region Public methods - public virtual void Selected(ILogLineColumnizerCallback callback) - { - ColumnList.Clear(); - ColumnSet.Clear(); + public virtual void Selected(ILogLineColumnizerCallback callback) + { + ColumnList.Clear(); + ColumnSet.Clear(); - var line = callback.GetLogLine(0); + var line = callback.GetLogLine(0); - if (line != null) + if (line != null) + { + var json = ParseJson(line); + if (json != null) { - var json = ParseJson(line); - if (json != null) - { - var fieldCount = json.Properties().Count(); + var fieldCount = json.Properties().Count(); - for (var i = 0; i < fieldCount; ++i) + for (var i = 0; i < fieldCount; ++i) + { + var columeName = json.Properties().ToArray()[i].Name; + if (!ColumnSet.Contains(columeName)) { - var columeName = json.Properties().ToArray()[i].Name; - if (!ColumnSet.Contains(columeName)) - { - ColumnSet.Add(columeName); - ColumnList.Add(new JsonColumn(columeName)); - } + ColumnSet.Add(columeName); + ColumnList.Add(new JsonColumn(columeName)); } } - else - { - ColumnSet.Add("Text"); - ColumnList.Add(InitialColumn); - } } - - if (ColumnList.Count() == 0) + else { ColumnSet.Add("Text"); ColumnList.Add(InitialColumn); } } - public virtual void DeSelected(ILogLineColumnizerCallback callback) + if (ColumnList.Count() == 0) { - // nothing to do + ColumnSet.Add("Text"); + ColumnList.Add(InitialColumn); } + } - public virtual string GetName() - { - return "JSON Columnizer"; - } + public virtual void DeSelected(ILogLineColumnizerCallback callback) + { + // nothing to do + } - public virtual string GetDescription() + public virtual string GetName() + { + return "JSON Columnizer"; + } + + public virtual string GetDescription() + { + return "Splits JSON files into columns.\r\n\r\nCredits:\r\nThis Columnizer uses the Newtonsoft json package.\r\n\r\nFirst line must be valid or else only one column will be displayed and the other values dropped!"; + } + + public virtual int GetColumnCount() + { + return ColumnList.Count; + } + + public virtual string[] GetColumnNames() + { + var names = new string[GetColumnCount()]; + var i = 0; + foreach (var column in ColumnList) { - return "Splits JSON files into columns.\r\n\r\nCredits:\r\nThis Columnizer uses the Newtonsoft json package.\r\n\r\nFirst line must be valid or else only one column will be displayed and the other values dropped!"; + names[i++] = column.Name; } - public virtual int GetColumnCount() + return names; + } + + public virtual IColumnizedLogLine SplitLine(ILogLineColumnizerCallback callback, ILogLine line) + { + JObject json = ParseJson(line); + + if (json != null) { - return ColumnList.Count; + return SplitJsonLine(line, json); } - public virtual string[] GetColumnNames() - { - string[] names = new string[GetColumnCount()]; - int i = 0; - foreach (var column in ColumnList) - { - names[i++] = column.Name; - } + var cLogLine = new ColumnizedLogLine { LogLine = line }; - return names; - } + var columns = Column.CreateColumns(ColumnList.Count, cLogLine); - public virtual IColumnizedLogLine SplitLine(ILogLineColumnizerCallback callback, ILogLine line) - { - JObject json = ParseJson(line); + columns.Last().FullValue = line.FullLine; - if (json != null) - { - return SplitJsonLine(line, json); - } + cLogLine.ColumnValues = columns.Select(a => (IColumn)a).ToArray(); - var cLogLine = new ColumnizedLogLine { LogLine = line }; + return cLogLine; + } - var columns = Column.CreateColumns(ColumnList.Count, cLogLine); + public virtual bool IsTimeshiftImplemented() + { + return false; + } - columns.Last().FullValue = line.FullLine; + public virtual void SetTimeOffset(int msecOffset) + { + throw new NotImplementedException(); + } - cLogLine.ColumnValues = columns.Select(a => (IColumn)a).ToArray(); + public virtual int GetTimeOffset() + { + throw new NotImplementedException(); + } - return cLogLine; - } + public virtual DateTime GetTimestamp(ILogLineColumnizerCallback callback, ILogLine line) + { + throw new NotImplementedException(); + } - public virtual bool IsTimeshiftImplemented() - { - return false; - } + public virtual void PushValue(ILogLineColumnizerCallback callback, int column, string value, string oldValue) + { + throw new NotImplementedException(); + } - public virtual void SetTimeOffset(int msecOffset) + public virtual Priority GetPriority(string fileName, IEnumerable samples) + { + Priority result = Priority.NotSupport; + if (fileName.EndsWith("json", StringComparison.OrdinalIgnoreCase)) { - throw new NotImplementedException(); + result = Priority.WellSupport; } - public virtual int GetTimeOffset() - { - throw new NotImplementedException(); - } + return result; + } - public virtual DateTime GetTimestamp(ILogLineColumnizerCallback callback, ILogLine line) - { - throw new NotImplementedException(); - } + #endregion - public virtual void PushValue(ILogLineColumnizerCallback callback, int column, string value, string oldValue) - { - throw new NotImplementedException(); - } + #region Private Methods - public virtual Priority GetPriority(string fileName, IEnumerable samples) + protected static JObject ParseJson(ILogLine line) + { + return JsonConvert.DeserializeObject(line.FullLine, new JsonSerializerSettings() { - Priority result = Priority.NotSupport; - if (fileName.EndsWith("json", StringComparison.OrdinalIgnoreCase)) - { - result = Priority.WellSupport; - } + Error = (sender, args) => { args.ErrorContext.Handled = true; } //We ignore the error and handle the null value + }); + } - return result; - } + public class ColumnWithName : Column + { + public string ColumnName { get; set; } + } - #endregion + // + // Following two log lines should be loaded and displayed in correct grid. + // {"time":"2019-02-13T02:55:35.5186240Z","message":"Hosting starting"} + // {"time":"2019-02-13T02:55:35.5186240Z","level":"warning", "message":"invalid host."} + // + protected virtual IColumnizedLogLine SplitJsonLine(ILogLine line, JObject json) + { + var cLogLine = new ColumnizedLogLine { LogLine = line }; - #region Private Methods + var columns = json.Properties().Select(property => new ColumnWithName { FullValue = property.Value.ToString(), ColumnName = property.Name.ToString(), Parent = cLogLine }).ToList(); - protected static JObject ParseJson(ILogLine line) + foreach (var jsonColumn in columns) { - return JsonConvert.DeserializeObject(line.FullLine, new JsonSerializerSettings() + // When find new column in a log line, add a new column in the end of the list. + if (!ColumnSet.Contains(jsonColumn.ColumnName)) { - Error = (sender, args) => { args.ErrorContext.Handled = true; } //We ignore the error and handle the null value - }); - } + if (ColumnList.Count == 1 && !ColumnSet.Contains(ColumnList[0].Name)) + { + ColumnList.Clear(); + } - public class ColumnWithName : Column - { - public string ColumnName { get; set; } + ColumnSet.Add(jsonColumn.ColumnName); + ColumnList.Add(new JsonColumn(jsonColumn.ColumnName)); + } } // - // Following two log lines should be loaded and displayed in correct grid. - // {"time":"2019-02-13T02:55:35.5186240Z","message":"Hosting starting"} - // {"time":"2019-02-13T02:55:35.5186240Z","level":"warning", "message":"invalid host."} + // Always rearrage the order of all json fields within a line to follow the sequence of columnNameList. + // This will make sure the log line displayed correct even the order of json fields changed. // - protected virtual IColumnizedLogLine SplitJsonLine(ILogLine line, JObject json) + List returnColumns = []; + foreach (var column in ColumnList) { - var cLogLine = new ColumnizedLogLine { LogLine = line }; - - var columns = json.Properties().Select(property => new ColumnWithName { FullValue = property.Value.ToString(), ColumnName = property.Name.ToString(), Parent = cLogLine }).ToList(); - - foreach (var jsonColumn in columns) - { - // When find new column in a log line, add a new column in the end of the list. - if (!ColumnSet.Contains(jsonColumn.ColumnName)) - { - if (ColumnList.Count == 1 && !ColumnSet.Contains(ColumnList[0].Name)) - { - ColumnList.Clear(); - } - - ColumnSet.Add(jsonColumn.ColumnName); - ColumnList.Add(new JsonColumn(jsonColumn.ColumnName)); - } - } - - // - // Always rearrage the order of all json fields within a line to follow the sequence of columnNameList. - // This will make sure the log line displayed correct even the order of json fields changed. - // - List returnColumns = []; - foreach (var column in ColumnList) + var existingColumn = columns.Find(x => x.ColumnName == column.Name); + if (existingColumn != null) { - var existingColumn = columns.Find(x => x.ColumnName == column.Name); - if (existingColumn != null) - { - returnColumns.Add(new Column() { FullValue = existingColumn.FullValue, Parent = cLogLine }); - continue; - } - - // Fields that is missing in current line should be shown as empty. - returnColumns.Add(new Column() { FullValue = "", Parent = cLogLine }); + returnColumns.Add(new Column() { FullValue = existingColumn.FullValue, Parent = cLogLine }); + continue; } - cLogLine.ColumnValues = [.. returnColumns]; - - return cLogLine; + // Fields that is missing in current line should be shown as empty. + returnColumns.Add(new Column() { FullValue = "", Parent = cLogLine }); } - #endregion + cLogLine.ColumnValues = [.. returnColumns]; + + return cLogLine; } + + #endregion } \ No newline at end of file diff --git a/src/JsonCompactColumnizer/JsonCompactColumnizer.cs b/src/JsonCompactColumnizer/JsonCompactColumnizer.cs index 32acccf8..d286ac88 100644 --- a/src/JsonCompactColumnizer/JsonCompactColumnizer.cs +++ b/src/JsonCompactColumnizer/JsonCompactColumnizer.cs @@ -6,116 +6,115 @@ using System.Collections.Generic; using System.Linq; -namespace JsonColumnizer +namespace JsonColumnizer; + +/// +/// This Columnizer can parse JSON files. +/// +public class JsonCompactColumnizer : JsonColumnizer, IColumnizerPriority { - /// - /// This Columnizer can parse JSON files. - /// - public class JsonCompactColumnizer : JsonColumnizer, IColumnizerPriority + #region Public methods + + public override string GetName() { - #region Public methods + return "JSON Compact Columnizer"; + } - public override string GetName() - { - return "JSON Compact Columnizer"; - } + public override string GetDescription() + { + return "A JSON columnier for Serilog.Formatting.Compact format."; + } - public override string GetDescription() + public override void Selected(ILogLineColumnizerCallback callback) + { + ColumnList.Clear(); + // Create column header with cached column list. + + foreach (var col in _tagDict.Keys) { - return "A JSON columnier for Serilog.Formatting.Compact format."; + ColumnList.Add(new JsonColumn(_tagDict[col])); } + } - public override void Selected(ILogLineColumnizerCallback callback) + public override Priority GetPriority(string fileName, IEnumerable samples) + { + Priority result = Priority.NotSupport; + if (fileName.EndsWith("json", StringComparison.OrdinalIgnoreCase)) { - ColumnList.Clear(); - // Create column header with cached column list. - - foreach (var col in _tagDict.Keys) - { - ColumnList.Add(new JsonColumn(_tagDict[col])); - } + result = Priority.WellSupport; } - public override Priority GetPriority(string fileName, IEnumerable samples) + if (samples != null && samples.Any()) { - Priority result = Priority.NotSupport; - if (fileName.EndsWith("json", StringComparison.OrdinalIgnoreCase)) - { - result = Priority.WellSupport; - } - - if (samples != null && samples.Any()) + try { - try + var line = samples.First(); + JObject json = ParseJson(line); + if (json != null) { - var line = samples.First(); - JObject json = ParseJson(line); - if (json != null) + var columns = SplitJsonLine(samples.First(), json); + if (columns.ColumnValues.Length > 0 && Array.Exists(columns.ColumnValues, x => !string.IsNullOrEmpty(x.FullValue))) { - var columns = SplitJsonLine(samples.First(), json); - if (columns.ColumnValues.Length > 0 && Array.Exists(columns.ColumnValues, x => !string.IsNullOrEmpty(x.FullValue))) - { - result = Priority.PerfectlySupport; - } + result = Priority.PerfectlySupport; } } - catch (Exception) - { - // Ignore errors when determine priority. - } } - - return result; + catch (Exception) + { + // Ignore errors when determine priority. + } } - #endregion + return result; + } - #region Private Methods + #endregion - protected Dictionary _tagDict = new() - { - {"@t", "Timestamp"}, - {"@l", "Level"}, - {"@m", "Message"}, - {"@x", "Exception"}, - {"@i", "Event id"}, - {"@r", "Renderings"}, - {"@mt", "Message Template"}, - }; - - protected override IColumnizedLogLine SplitJsonLine(ILogLine line, JObject json) - { - List returnColumns = []; - var cLogLine = new ColumnizedLogLine { LogLine = line }; + #region Private Methods - var columns = json.Properties().Select(property => new ColumnWithName { FullValue = property.Value.ToString(), ColumnName = property.Name.ToString(), Parent = cLogLine }).ToList(); + protected Dictionary _tagDict = new() + { + {"@t", "Timestamp"}, + {"@l", "Level"}, + {"@m", "Message"}, + {"@x", "Exception"}, + {"@i", "Event id"}, + {"@r", "Renderings"}, + {"@mt", "Message Template"}, + }; + + protected override IColumnizedLogLine SplitJsonLine(ILogLine line, JObject json) + { + List returnColumns = []; + var cLogLine = new ColumnizedLogLine { LogLine = line }; - // - // Always rearrage the order of all json fields within a line to follow the sequence of columnNameList. - // This will make sure the log line displayed correct even the order of json fields changed. - // - foreach (var column in _tagDict.Keys) - { - if (column.StartsWith('@')) - { - var existingColumn = columns.Find(x => x.ColumnName == column); + var columns = json.Properties().Select(property => new ColumnWithName { FullValue = property.Value.ToString(), ColumnName = property.Name.ToString(), Parent = cLogLine }).ToList(); - if (existingColumn != null) - { - returnColumns.Add(new Column() { FullValue = existingColumn.FullValue, Parent = cLogLine }); - continue; - } + // + // Always rearrage the order of all json fields within a line to follow the sequence of columnNameList. + // This will make sure the log line displayed correct even the order of json fields changed. + // + foreach (var column in _tagDict.Keys) + { + if (column.StartsWith('@')) + { + var existingColumn = columns.Find(x => x.ColumnName == column); - // Fields that is missing in current line should be shown as empty. - returnColumns.Add(new Column() { FullValue = "", Parent = cLogLine }); + if (existingColumn != null) + { + returnColumns.Add(new Column() { FullValue = existingColumn.FullValue, Parent = cLogLine }); + continue; } - } - cLogLine.ColumnValues = [.. returnColumns]; - - return cLogLine; + // Fields that is missing in current line should be shown as empty. + returnColumns.Add(new Column() { FullValue = "", Parent = cLogLine }); + } } - #endregion + cLogLine.ColumnValues = [.. returnColumns]; + + return cLogLine; } + + #endregion } \ No newline at end of file diff --git a/src/Log4jXmlColumnizer/Log4JLogLine.cs b/src/Log4jXmlColumnizer/Log4JLogLine.cs index d6b09125..616a1939 100644 --- a/src/Log4jXmlColumnizer/Log4JLogLine.cs +++ b/src/Log4jXmlColumnizer/Log4JLogLine.cs @@ -1,17 +1,16 @@ using LogExpert; -namespace Log4jXmlColumnizer +namespace Log4jXmlColumnizer; + +internal class Log4JLogLine : ILogLine { - internal class Log4JLogLine : ILogLine - { - #region Properties + #region Properties - public string FullLine { get; set; } + public string FullLine { get; set; } - public int LineNumber { get; set; } + public int LineNumber { get; set; } - string ITextValue.Text => FullLine; + string ITextValue.Text => FullLine; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/Log4jXmlColumnizer/Log4jColumnEntry.cs b/src/Log4jXmlColumnizer/Log4jColumnEntry.cs index b1d7869a..ad0e4f39 100644 --- a/src/Log4jXmlColumnizer/Log4jColumnEntry.cs +++ b/src/Log4jXmlColumnizer/Log4jColumnEntry.cs @@ -1,19 +1,18 @@ using System; -namespace Log4jXmlColumnizer +namespace Log4jXmlColumnizer; + +/// +/// Helper class for configuration of the columns. +/// +[Serializable] +public class Log4jColumnEntry(string name, int index, int maxLen) { - /// - /// Helper class for configuration of the columns. - /// - [Serializable] - public class Log4jColumnEntry(string name, int index, int maxLen) - { - public int ColumnIndex { get; set; } = index; + public int ColumnIndex { get; set; } = index; - public string ColumnName { get; set; } = name; + public string ColumnName { get; set; } = name; - public int MaxLen { get; set; } = maxLen; + public int MaxLen { get; set; } = maxLen; - public bool Visible { get; set; } - } + public bool Visible { get; set; } } \ No newline at end of file diff --git a/src/Log4jXmlColumnizer/Log4jXmlColumnizer.cs b/src/Log4jXmlColumnizer/Log4jXmlColumnizer.cs index a221c39b..012bd06b 100644 --- a/src/Log4jXmlColumnizer/Log4jXmlColumnizer.cs +++ b/src/Log4jXmlColumnizer/Log4jXmlColumnizer.cs @@ -12,300 +12,299 @@ using System.Windows.Forms; [assembly: SupportedOSPlatform("windows")] -namespace Log4jXmlColumnizer +namespace Log4jXmlColumnizer; + +public class Log4jXmlColumnizer : ILogLineXmlColumnizer, IColumnizerConfigurator, IColumnizerPriority { - public class Log4jXmlColumnizer : ILogLineXmlColumnizer, IColumnizerConfigurator, IColumnizerPriority - { - #region Fields + #region Fields - public const int COLUMN_COUNT = 9; - protected const string DATETIME_FORMAT = "dd.MM.yyyy HH:mm:ss.fff"; + public const int COLUMN_COUNT = 9; + protected const string DATETIME_FORMAT = "dd.MM.yyyy HH:mm:ss.fff"; - private static readonly XmlConfig xmlConfig = new(); - private readonly char separatorChar = '\xFFFD'; - private readonly char[] trimChars = ['\xFFFD']; - private Log4jXmlColumnizerConfig _config; - protected CultureInfo cultureInfo = new("de-DE"); - protected int timeOffset = 0; + private static readonly XmlConfig xmlConfig = new(); + private readonly char separatorChar = '\xFFFD'; + private readonly char[] trimChars = ['\xFFFD']; + private Log4jXmlColumnizerConfig _config; + protected CultureInfo cultureInfo = new("de-DE"); + protected int timeOffset; - #endregion + #endregion - #region cTor + #region cTor - public Log4jXmlColumnizer() - { - _config = new Log4jXmlColumnizerConfig(GetAllColumnNames()); - } + public Log4jXmlColumnizer() + { + _config = new Log4jXmlColumnizerConfig(GetAllColumnNames()); + } - #endregion + #endregion - #region Public methods + #region Public methods - public IXmlLogConfiguration GetXmlLogConfiguration() - { - return xmlConfig; - } + public IXmlLogConfiguration GetXmlLogConfiguration() + { + return xmlConfig; + } - public ILogLine GetLineTextForClipboard(ILogLine logLine, ILogLineColumnizerCallback callback) + public ILogLine GetLineTextForClipboard(ILogLine logLine, ILogLineColumnizerCallback callback) + { + Log4JLogLine line = new() { - Log4JLogLine line = new() - { - FullLine = logLine.FullLine.Replace(separatorChar, '|'), - LineNumber = logLine.LineNumber - }; + FullLine = logLine.FullLine.Replace(separatorChar, '|'), + LineNumber = logLine.LineNumber + }; - return line; - } + return line; + } - public string GetName() - { - return "Log4j XML"; - } + public string GetName() + { + return "Log4j XML"; + } - public string GetDescription() - { - return "Reads and formats XML log files written with log4j."; - } + public string GetDescription() + { + return "Reads and formats XML log files written with log4j."; + } - public int GetColumnCount() - { - return _config.ActiveColumnCount; - } + public int GetColumnCount() + { + return _config.ActiveColumnCount; + } + + public string[] GetColumnNames() + { + return _config.ActiveColumnNames; + } + + public IColumnizedLogLine SplitLine(ILogLineColumnizerCallback callback, ILogLine line) + { + ColumnizedLogLine clogLine = new(); + clogLine.LogLine = line; - public string[] GetColumnNames() + Column[] columns = Column.CreateColumns(COLUMN_COUNT, clogLine); + + // If the line is too short (i.e. does not follow the format for this columnizer) return the whole line content + // in colum 8 (the log message column). Date and time column will be left blank. + if (line.FullLine.Length < 15) { - return _config.ActiveColumnNames; + columns[8].FullValue = line.FullLine; } - - public IColumnizedLogLine SplitLine(ILogLineColumnizerCallback callback, ILogLine line) + else { - ColumnizedLogLine clogLine = new(); - clogLine.LogLine = line; + try + { + DateTime dateTime = GetTimestamp(callback, line); + + if (dateTime == DateTime.MinValue) + { + columns[8].FullValue = line.FullLine; + } - Column[] columns = Column.CreateColumns(COLUMN_COUNT, clogLine); + var newDate = dateTime.ToString(DATETIME_FORMAT); + columns[0].FullValue = newDate; + } + catch (Exception) + { + columns[0].FullValue = "n/a"; + } - // If the line is too short (i.e. does not follow the format for this columnizer) return the whole line content - // in colum 8 (the log message column). Date and time column will be left blank. - if (line.FullLine.Length < 15) + Column timestmp = columns[0]; + + string[] cols; + cols = line.FullLine.Split(trimChars, COLUMN_COUNT, StringSplitOptions.None); + + if (cols.Length != COLUMN_COUNT) { + columns[0].FullValue = ""; + columns[1].FullValue = ""; + columns[2].FullValue = ""; + columns[3].FullValue = ""; + columns[4].FullValue = ""; + columns[5].FullValue = ""; + columns[6].FullValue = ""; + columns[7].FullValue = ""; columns[8].FullValue = line.FullLine; } else { - try - { - DateTime dateTime = GetTimestamp(callback, line); - - if (dateTime == DateTime.MinValue) - { - columns[8].FullValue = line.FullLine; - } + columns[0] = timestmp; - string newDate = dateTime.ToString(DATETIME_FORMAT); - columns[0].FullValue = newDate; - } - catch (Exception) + for (var i = 1; i < cols.Length; i++) { - columns[0].FullValue = "n/a"; + columns[i].FullValue = cols[i]; } + } + } - Column timestmp = columns[0]; - - string[] cols; - cols = line.FullLine.Split(trimChars, COLUMN_COUNT, StringSplitOptions.None); + Column[] filteredColumns = MapColumns(columns); - if (cols.Length != COLUMN_COUNT) - { - columns[0].FullValue = ""; - columns[1].FullValue = ""; - columns[2].FullValue = ""; - columns[3].FullValue = ""; - columns[4].FullValue = ""; - columns[5].FullValue = ""; - columns[6].FullValue = ""; - columns[7].FullValue = ""; - columns[8].FullValue = line.FullLine; - } - else - { - columns[0] = timestmp; + clogLine.ColumnValues = filteredColumns.Select(a => a as IColumn).ToArray(); - for (int i = 1; i < cols.Length; i++) - { - columns[i].FullValue = cols[i]; - } - } - } - Column[] filteredColumns = MapColumns(columns); + return clogLine; + } - clogLine.ColumnValues = filteredColumns.Select(a => a as IColumn).ToArray(); + public bool IsTimeshiftImplemented() + { + return true; + } - return clogLine; - } + public void SetTimeOffset(int msecOffset) + { + timeOffset = msecOffset; + } + public int GetTimeOffset() + { + return timeOffset; + } - public bool IsTimeshiftImplemented() + public DateTime GetTimestamp(ILogLineColumnizerCallback callback, ILogLine line) + { + if (line.FullLine.Length < 15) { - return true; + return DateTime.MinValue; } - public void SetTimeOffset(int msecOffset) - { - timeOffset = msecOffset; - } + var endIndex = line.FullLine.IndexOf(separatorChar, 1); - public int GetTimeOffset() + if (endIndex > 20 || endIndex < 0) { - return timeOffset; + return DateTime.MinValue; } + var value = line.FullLine.Substring(0, endIndex); - public DateTime GetTimestamp(ILogLineColumnizerCallback callback, ILogLine line) + try { - if (line.FullLine.Length < 15) - { - return DateTime.MinValue; - } - - int endIndex = line.FullLine.IndexOf(separatorChar, 1); - - if (endIndex > 20 || endIndex < 0) + // convert log4j timestamp into a readable format: + if (long.TryParse(value, out var timestamp)) { - return DateTime.MinValue; - } - string value = line.FullLine.Substring(0, endIndex); + // Add the time offset before returning + DateTime dateTime = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + dateTime = dateTime.AddMilliseconds(timestamp); - try - { - // convert log4j timestamp into a readable format: - if (long.TryParse(value, out long timestamp)) - { - // Add the time offset before returning - DateTime dateTime = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); - dateTime = dateTime.AddMilliseconds(timestamp); - - if (_config.localTimestamps) - { - dateTime = dateTime.ToLocalTime(); - } - return dateTime.AddMilliseconds(timeOffset); - } - else + if (_config.localTimestamps) { - return DateTime.MinValue; + dateTime = dateTime.ToLocalTime(); } + return dateTime.AddMilliseconds(timeOffset); } - catch (Exception) + else { return DateTime.MinValue; } } + catch (Exception) + { + return DateTime.MinValue; + } + } - public void PushValue(ILogLineColumnizerCallback callback, int column, string value, string oldValue) + public void PushValue(ILogLineColumnizerCallback callback, int column, string value, string oldValue) + { + if (column == 0) { - if (column == 0) + try + { + var newDateTime = DateTime.ParseExact(value, DATETIME_FORMAT, cultureInfo); + var oldDateTime = DateTime.ParseExact(oldValue, DATETIME_FORMAT, cultureInfo); + var mSecsOld = oldDateTime.Ticks / TimeSpan.TicksPerMillisecond; + var mSecsNew = newDateTime.Ticks / TimeSpan.TicksPerMillisecond; + timeOffset = (int)(mSecsNew - mSecsOld); + } + catch (FormatException) { - try - { - DateTime newDateTime = DateTime.ParseExact(value, DATETIME_FORMAT, cultureInfo); - DateTime oldDateTime = DateTime.ParseExact(oldValue, DATETIME_FORMAT, cultureInfo); - long mSecsOld = oldDateTime.Ticks / TimeSpan.TicksPerMillisecond; - long mSecsNew = newDateTime.Ticks / TimeSpan.TicksPerMillisecond; - timeOffset = (int)(mSecsNew - mSecsOld); - } - catch (FormatException) - { - } } } + } - public void Configure(ILogLineColumnizerCallback callback, string configDir) - { - FileInfo fileInfo = new(configDir + Path.DirectorySeparatorChar + "log4jxmlcolumnizer.json"); + public void Configure(ILogLineColumnizerCallback callback, string configDir) + { + FileInfo fileInfo = new(configDir + Path.DirectorySeparatorChar + "log4jxmlcolumnizer.json"); - Log4jXmlColumnizerConfigDlg dlg = new(_config); + Log4jXmlColumnizerConfigDlg dlg = new(_config); - if (dlg.ShowDialog() == DialogResult.OK) - { - using StreamWriter sw = new(fileInfo.Create()); - JsonSerializer serializer = new(); - serializer.Serialize(sw, _config); - } + if (dlg.ShowDialog() == DialogResult.OK) + { + using StreamWriter sw = new(fileInfo.Create()); + JsonSerializer serializer = new(); + serializer.Serialize(sw, _config); } + } - public void LoadConfig(string configDir) - { - string configPath = configDir + Path.DirectorySeparatorChar + "log4jxmlcolumnizer.json"; + public void LoadConfig(string configDir) + { + var configPath = configDir + Path.DirectorySeparatorChar + "log4jxmlcolumnizer.json"; - FileInfo fileInfo = new(configDir + Path.DirectorySeparatorChar + "log4jxmlcolumnizer.json"); + FileInfo fileInfo = new(configDir + Path.DirectorySeparatorChar + "log4jxmlcolumnizer.json"); - if (!File.Exists(configPath)) - { - _config = new Log4jXmlColumnizerConfig(GetAllColumnNames()); - } - else + if (!File.Exists(configPath)) + { + _config = new Log4jXmlColumnizerConfig(GetAllColumnNames()); + } + else + { + try { - try - { - _config = JsonConvert.DeserializeObject(File.ReadAllText($"{fileInfo.FullName}")); - if (_config.columnList.Count < COLUMN_COUNT) - { - _config = new Log4jXmlColumnizerConfig(GetAllColumnNames()); - } - } - catch (SerializationException e) + _config = JsonConvert.DeserializeObject(File.ReadAllText($"{fileInfo.FullName}")); + if (_config.columnList.Count < COLUMN_COUNT) { - MessageBox.Show(e.Message, "Deserialize"); _config = new Log4jXmlColumnizerConfig(GetAllColumnNames()); } } + catch (SerializationException e) + { + MessageBox.Show(e.Message, "Deserialize"); + _config = new Log4jXmlColumnizerConfig(GetAllColumnNames()); + } } + } - public Priority GetPriority(string fileName, IEnumerable samples) + public Priority GetPriority(string fileName, IEnumerable samples) + { + Priority result = Priority.NotSupport; + if (fileName.EndsWith("xml", StringComparison.OrdinalIgnoreCase)) { - Priority result = Priority.NotSupport; - if (fileName.EndsWith("xml", StringComparison.OrdinalIgnoreCase)) - { - result = Priority.CanSupport; - } - return result; + result = Priority.CanSupport; } + return result; + } - #endregion + #endregion - #region Private Methods + #region Private Methods - private string[] GetAllColumnNames() => ["Timestamp", "Level", "Logger", "Thread", "Class", "Method", "File", "Line", "Message"]; + private string[] GetAllColumnNames() => ["Timestamp", "Level", "Logger", "Thread", "Class", "Method", "File", "Line", "Message"]; - /// - /// Returns only the columns which are "active". The order of the columns depends on the column order in the config - /// - /// - /// - private Column[] MapColumns(Column[] cols) + /// + /// Returns only the columns which are "active". The order of the columns depends on the column order in the config + /// + /// + /// + private Column[] MapColumns(Column[] cols) + { + List output = []; + var index = 0; + foreach (Log4jColumnEntry entry in _config.columnList) { - List output = []; - int index = 0; - foreach (Log4jColumnEntry entry in _config.columnList) + if (entry.Visible) { - if (entry.Visible) - { - Column column = cols[index]; - output.Add(column); + Column column = cols[index]; + output.Add(column); - if (entry.MaxLen > 0 && column.FullValue.Length > entry.MaxLen) - { - column.FullValue = column.FullValue.Substring(column.FullValue.Length - entry.MaxLen); - } + if (entry.MaxLen > 0 && column.FullValue.Length > entry.MaxLen) + { + column.FullValue = column.FullValue.Substring(column.FullValue.Length - entry.MaxLen); } - index++; } - - - return [.. output]; + index++; } - #endregion + + return [.. output]; } + + #endregion } \ No newline at end of file diff --git a/src/Log4jXmlColumnizer/Log4jXmlColumnizerConfig.cs b/src/Log4jXmlColumnizer/Log4jXmlColumnizerConfig.cs index 7954f47c..186a7cfd 100644 --- a/src/Log4jXmlColumnizer/Log4jXmlColumnizerConfig.cs +++ b/src/Log4jXmlColumnizer/Log4jXmlColumnizerConfig.cs @@ -1,82 +1,81 @@ using System; using System.Collections.Generic; -namespace Log4jXmlColumnizer +namespace Log4jXmlColumnizer; + +[Serializable] +public class Log4jXmlColumnizerConfig { - [Serializable] - public class Log4jXmlColumnizerConfig - { - #region Fields + #region Fields - public List columnList = []; - public bool localTimestamps = true; + public List columnList = []; + public bool localTimestamps = true; - #endregion + #endregion - #region cTor + #region cTor - public Log4jXmlColumnizerConfig(string[] columnNames) - { - FillDefaults(columnNames); - } + public Log4jXmlColumnizerConfig(string[] columnNames) + { + FillDefaults(columnNames); + } - #endregion + #endregion - #region Properties + #region Properties - /// - /// Returns the column count. Because the user can deactivate columns in the config - /// the actual column count may be smaller than the number of available columns. - /// - public int ActiveColumnCount + /// + /// Returns the column count. Because the user can deactivate columns in the config + /// the actual column count may be smaller than the number of available columns. + /// + public int ActiveColumnCount + { + get { - get + var count = 0; + foreach (Log4jColumnEntry entry in columnList) { - int count = 0; - foreach (Log4jColumnEntry entry in columnList) + if (entry.Visible) { - if (entry.Visible) - { - count++; - } + count++; } - return count; } + return count; } + } - /// - /// Returns the names of all active columns. - /// - public string[] ActiveColumnNames + /// + /// Returns the names of all active columns. + /// + public string[] ActiveColumnNames + { + get { - get + var names = new string[ActiveColumnCount]; + var index = 0; + foreach (Log4jColumnEntry entry in columnList) { - string[] names = new string[ActiveColumnCount]; - int index = 0; - foreach (Log4jColumnEntry entry in columnList) + if (entry.Visible) { - if (entry.Visible) - { - names[index++] = entry.ColumnName; - } + names[index++] = entry.ColumnName; } - return names; } + return names; } + } - #endregion + #endregion - #region Public methods + #region Public methods - public void FillDefaults(string[] columnNames) + public void FillDefaults(string[] columnNames) + { + columnList.Clear(); + for (var i = 0; i < columnNames.Length; ++i) { - columnList.Clear(); - for (int i = 0; i < columnNames.Length; ++i) - { - columnList.Add(new Log4jColumnEntry(columnNames[i], i, 0)); - } + columnList.Add(new Log4jColumnEntry(columnNames[i], i, 0)); } - - #endregion } + + #endregion } \ No newline at end of file diff --git a/src/Log4jXmlColumnizer/Log4jXmlColumnizerConfigDlg.cs b/src/Log4jXmlColumnizer/Log4jXmlColumnizerConfigDlg.cs index 5ce046d7..a07ff9b3 100644 --- a/src/Log4jXmlColumnizer/Log4jXmlColumnizerConfigDlg.cs +++ b/src/Log4jXmlColumnizer/Log4jXmlColumnizerConfigDlg.cs @@ -4,81 +4,80 @@ using System.Drawing; using System.Windows.Forms; -namespace LogExpert +namespace LogExpert; + +public partial class Log4jXmlColumnizerConfigDlg : Form { - public partial class Log4jXmlColumnizerConfigDlg : Form + #region Fields + + private readonly Log4jXmlColumnizerConfig _config; + + #endregion + + #region cTor + + public Log4jXmlColumnizerConfigDlg(Log4jXmlColumnizerConfig config) { - #region Fields + SuspendLayout(); + AutoScaleDimensions = new SizeF(96F, 96F); + AutoScaleMode = AutoScaleMode.Dpi; + + _config = config; + InitializeComponent(); + FillListBox(); + localTimeCheckBox.Checked = _config.localTimestamps; + ResumeLayout(); + } - private readonly Log4jXmlColumnizerConfig _config; + #endregion - #endregion + #region Private Methods - #region cTor + private void FillListBox() + { + var checkColumn = (DataGridViewCheckBoxColumn)columnGridView.Columns[0]; + var nameColumn = (DataGridViewTextBoxColumn)columnGridView.Columns[1]; + var lenColumn = (DataGridViewTextBoxColumn)columnGridView.Columns[2]; - public Log4jXmlColumnizerConfigDlg(Log4jXmlColumnizerConfig config) + foreach (Log4jColumnEntry entry in _config.columnList) { - SuspendLayout(); - AutoScaleDimensions = new SizeF(96F, 96F); - AutoScaleMode = AutoScaleMode.Dpi; - - _config = config; - InitializeComponent(); - FillListBox(); - localTimeCheckBox.Checked = _config.localTimestamps; - ResumeLayout(); + DataGridViewRow row = new(); + row.Cells.Add(new DataGridViewCheckBoxCell()); + row.Cells.Add(new DataGridViewTextBoxCell()); + row.Cells.Add(new DataGridViewTextBoxCell()); + row.Cells[0].Value = entry.Visible; + row.Cells[1].Value = entry.ColumnName; + row.Cells[2].Value = entry.MaxLen > 0 ? "" + entry.MaxLen : ""; + columnGridView.Rows.Add(row); } + } - #endregion + #endregion - #region Private Methods + #region Events handler - private void FillListBox() + private void OkButton_Click(object sender, EventArgs e) + { + // for (int i = 0; i < this.config.columnList.Count; ++i) + // { + // this.config.columnList[i]. visible = this.columnListBox.GetItemChecked(i); + // } + for (var i = 0; i < columnGridView.Rows.Count; ++i) { - DataGridViewCheckBoxColumn checkColumn = (DataGridViewCheckBoxColumn)columnGridView.Columns[0]; - DataGridViewTextBoxColumn nameColumn = (DataGridViewTextBoxColumn)columnGridView.Columns[1]; - DataGridViewTextBoxColumn lenColumn = (DataGridViewTextBoxColumn)columnGridView.Columns[2]; + _config.columnList[i].Visible = (bool)columnGridView.Rows[i].Cells[0].Value; + var sLen = (string)columnGridView.Rows[i].Cells[2].Value; - foreach (Log4jColumnEntry entry in _config.columnList) + if (int.TryParse(sLen, out var len)) { - DataGridViewRow row = new(); - row.Cells.Add(new DataGridViewCheckBoxCell()); - row.Cells.Add(new DataGridViewTextBoxCell()); - row.Cells.Add(new DataGridViewTextBoxCell()); - row.Cells[0].Value = entry.Visible; - row.Cells[1].Value = entry.ColumnName; - row.Cells[2].Value = entry.MaxLen > 0 ? "" + entry.MaxLen : ""; - columnGridView.Rows.Add(row); + _config.columnList[i].MaxLen = len; } - } - - #endregion - - #region Events handler - - private void OkButton_Click(object sender, EventArgs e) - { - // for (int i = 0; i < this.config.columnList.Count; ++i) - // { - // this.config.columnList[i]. visible = this.columnListBox.GetItemChecked(i); - // } - for (int i = 0; i < columnGridView.Rows.Count; ++i) + else { - _config.columnList[i].Visible = (bool)columnGridView.Rows[i].Cells[0].Value; - string sLen = (string)columnGridView.Rows[i].Cells[2].Value; - - if (int.TryParse(sLen, out int len)) - { - _config.columnList[i].MaxLen = len; - } - else - { - _config.columnList[i].MaxLen = 0; - } + _config.columnList[i].MaxLen = 0; } - _config.localTimestamps = localTimeCheckBox.Checked; } - - #endregion + _config.localTimestamps = localTimeCheckBox.Checked; } + + #endregion } \ No newline at end of file diff --git a/src/Log4jXmlColumnizer/XmlConfig.cs b/src/Log4jXmlColumnizer/XmlConfig.cs index cd84e535..24620b82 100644 --- a/src/Log4jXmlColumnizer/XmlConfig.cs +++ b/src/Log4jXmlColumnizer/XmlConfig.cs @@ -1,36 +1,32 @@ using LogExpert; -namespace Log4jXmlColumnizer +namespace Log4jXmlColumnizer; + +/// +/// XMl configuration for parsing log4j XML files. The XSL will transform every block of log entries +/// into text lines. The fields in the text lines are separated by a special character (0xFFFD). +/// The special character will be used in the Split() function of the columnizer to split the line +/// into columns. +/// +internal class XmlConfig : IXmlLogConfiguration { - /// - /// XMl configuration for parsing log4j XML files. The XSL will transform every block of log entries - /// into text lines. The fields in the text lines are separated by a special character (0xFFFD). - /// The special character will be used in the Split() function of the columnizer to split the line - /// into columns. - /// - internal class XmlConfig : IXmlLogConfiguration - { - #region Properties + #region Properties - public string XmlStartTag { get; } = "" + - "" + - "" + - "" + - "" + - ""; + public string Stylesheet { get; } = "" + + "" + + "" + + "" + + "" + + "" + + ""; - public string[] Namespace - { - get { return ["log4j", "http://jakarta.apache.org/log4j"]; } - } + public string[] Namespace => ["log4j", "http://jakarta.apache.org/log4j"]; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Bookmark/BookmarkExporter.cs b/src/LogExpert.Core/Classes/Bookmark/BookmarkExporter.cs index 6cd3fa13..2100f803 100644 --- a/src/LogExpert.Core/Classes/Bookmark/BookmarkExporter.cs +++ b/src/LogExpert.Core/Classes/Bookmark/BookmarkExporter.cs @@ -18,7 +18,7 @@ public static void ExportBookmarkList (SortedList bookma writer.WriteLine("Log file name;Line number;Comment"); foreach (Entities.Bookmark bookmark in bookmarkList.Values) { - string line = $"{logfileName};{bookmark.LineNum};{bookmark.Text.Replace(replacementForNewLine, @"\" + replacementForNewLine, StringComparison.OrdinalIgnoreCase).Replace("\r\n", replacementForNewLine, StringComparison.OrdinalIgnoreCase)}"; + var line = $"{logfileName};{bookmark.LineNum};{bookmark.Text.Replace(replacementForNewLine, @"\" + replacementForNewLine, StringComparison.OrdinalIgnoreCase).Replace("\r\n", replacementForNewLine, StringComparison.OrdinalIgnoreCase)}"; writer.WriteLine(line); } writer.Close(); diff --git a/src/LogExpert.Core/Classes/Columnizer/ClfColumnizer.cs b/src/LogExpert.Core/Classes/Columnizer/ClfColumnizer.cs index 14dbe3f0..d5cf9614 100644 --- a/src/LogExpert.Core/Classes/Columnizer/ClfColumnizer.cs +++ b/src/LogExpert.Core/Classes/Columnizer/ClfColumnizer.cs @@ -3,181 +3,176 @@ using System.Linq; using System.Text.RegularExpressions; -namespace LogExpert.Core.Classes.Columnizer +namespace LogExpert.Core.Classes.Columnizer; + +public class ClfColumnizer : ILogLineColumnizer { - public class ClfColumnizer : ILogLineColumnizer - { - #region Fields + #region Fields - private readonly Regex lineRegex = new("(.*) (-) (.*) (\\[.*\\]) (\".*\") (.*) (.*) (\".*\") (\".*\")"); + private readonly Regex lineRegex = new("(.*) (-) (.*) (\\[.*\\]) (\".*\") (.*) (.*) (\".*\") (\".*\")"); - protected CultureInfo cultureInfo = new("de-DE"); - protected int timeOffset = 0; + protected CultureInfo cultureInfo = new("de-DE"); + protected int timeOffset; - #endregion + #endregion - #region cTor + #region cTor - // anon-212-34-174-126.suchen.de - - [08/Mar/2008:00:41:10 +0100] "GET /wiki/index.php?title=Bild:Poster_small.jpg&printable=yes&printable=yes HTTP/1.1" 304 0 "http://www.captain-kloppi.de/wiki/index.php?title=Bild:Poster_small.jpg&printable=yes" "gonzo1[P] +http://www.suchen.de/faq.html" + // anon-212-34-174-126.suchen.de - - [08/Mar/2008:00:41:10 +0100] "GET /wiki/index.php?title=Bild:Poster_small.jpg&printable=yes&printable=yes HTTP/1.1" 304 0 "http://www.captain-kloppi.de/wiki/index.php?title=Bild:Poster_small.jpg&printable=yes" "gonzo1[P] +http://www.suchen.de/faq.html" - public ClfColumnizer() - { - } + public ClfColumnizer() + { + } + + #endregion + + #region Public methods - #endregion + public bool IsTimeshiftImplemented() + { + return true; + } - #region Public methods + public void SetTimeOffset(int msecOffset) + { + timeOffset = msecOffset; + } - public bool IsTimeshiftImplemented() + public int GetTimeOffset() + { + return timeOffset; + } + + public DateTime GetTimestamp(LogExpert.ILogLineColumnizerCallback callback, ILogLine line) + { + IColumnizedLogLine cols = SplitLine(callback, line); + if (cols == null || cols.ColumnValues.Length < 8) { - return true; + return DateTime.MinValue; } - public void SetTimeOffset(int msecOffset) + if (cols.ColumnValues[2].FullValue.Length == 0) { - timeOffset = msecOffset; + return DateTime.MinValue; } - public int GetTimeOffset() + try { - return timeOffset; + var dateTime = DateTime.ParseExact(cols.ColumnValues[2].FullValue, "dd/MMM/yyyy:HH:mm:ss zzz", + new CultureInfo("en-US")); + return dateTime; } - - public DateTime GetTimestamp(LogExpert.ILogLineColumnizerCallback callback, ILogLine line) + catch (Exception) { - IColumnizedLogLine cols = SplitLine(callback, line); - if (cols == null || cols.ColumnValues.Length < 8) - { - return DateTime.MinValue; - } - - if (cols.ColumnValues[2].FullValue.Length == 0) - { - return DateTime.MinValue; - } + return DateTime.MinValue; + } + } + public void PushValue(LogExpert.ILogLineColumnizerCallback callback, int column, string value, string oldValue) + { + if (column == 2) + { try { - DateTime dateTime = DateTime.ParseExact(cols.ColumnValues[2].FullValue, "dd/MMM/yyyy:HH:mm:ss zzz", - new CultureInfo("en-US")); - return dateTime; + var newDateTime = + DateTime.ParseExact(value, "dd/MMM/yyyy:HH:mm:ss zzz", new CultureInfo("en-US")); + var oldDateTime = + DateTime.ParseExact(oldValue, "dd/MMM/yyyy:HH:mm:ss zzz", new CultureInfo("en-US")); + var mSecsOld = oldDateTime.Ticks / TimeSpan.TicksPerMillisecond; + var mSecsNew = newDateTime.Ticks / TimeSpan.TicksPerMillisecond; + timeOffset = (int)(mSecsNew - mSecsOld); } - catch (Exception) + catch (FormatException) { - return DateTime.MinValue; } } + } - public void PushValue(LogExpert.ILogLineColumnizerCallback callback, int column, string value, string oldValue) - { - if (column == 2) - { - try - { - DateTime newDateTime = - DateTime.ParseExact(value, "dd/MMM/yyyy:HH:mm:ss zzz", new CultureInfo("en-US")); - DateTime oldDateTime = - DateTime.ParseExact(oldValue, "dd/MMM/yyyy:HH:mm:ss zzz", new CultureInfo("en-US")); - long mSecsOld = oldDateTime.Ticks / TimeSpan.TicksPerMillisecond; - long mSecsNew = newDateTime.Ticks / TimeSpan.TicksPerMillisecond; - timeOffset = (int)(mSecsNew - mSecsOld); - } - catch (FormatException) - { - } - } - } + public string GetName() + { + return "Webserver CLF Columnizer"; + } - public string GetName() - { - return "Webserver CLF Columnizer"; - } + public string GetDescription() + { + return "Common Logfile Format used by webservers."; + } - public string GetDescription() - { - return "Common Logfile Format used by webservers."; - } + public int GetColumnCount() + { + return 8; + } + + public string[] GetColumnNames() + { + return ["IP", "User", "Date/Time", "Request", "Status", "Bytes", "Referrer", "User agent"]; + } - public int GetColumnCount() + public IColumnizedLogLine SplitLine(LogExpert.ILogLineColumnizerCallback callback, ILogLine line) + { + ColumnizedLogLine cLogLine = new() { - return 8; - } + LogLine = line + }; - public string[] GetColumnNames() + var columns = new Column[8] + { + new() {FullValue = "", Parent = cLogLine}, + new() {FullValue = "", Parent = cLogLine}, + new() {FullValue = "", Parent = cLogLine}, + new() {FullValue = "", Parent = cLogLine}, + new() {FullValue = "", Parent = cLogLine}, + new() {FullValue = "", Parent = cLogLine}, + new() {FullValue = "", Parent = cLogLine}, + new() {FullValue = "", Parent = cLogLine} + }; + + cLogLine.ColumnValues = columns.Select(a => a as IColumn).ToArray(); + + var temp = line.FullLine; + if (temp.Length > 1024) { - return new string[] { "IP", "User", "Date/Time", "Request", "Status", "Bytes", "Referrer", "User agent" }; + // spam + temp = temp.Substring(0, 1024); + columns[3].FullValue = temp; + return cLogLine; } + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + // anon-212-34-174-126.suchen.de - - [08/Mar/2008:00:41:10 +0100] "GET /wiki/index.php?title=Bild:Poster_small.jpg&printable=yes&printable=yes HTTP/1.1" 304 0 "http://www.captain-kloppi.de/wiki/index.php?title=Bild:Poster_small.jpg&printable=yes" "gonzo1[P] +http://www.suchen.de/faq.html" - public IColumnizedLogLine SplitLine(LogExpert.ILogLineColumnizerCallback callback, ILogLine line) + if (lineRegex.IsMatch(temp)) { - ColumnizedLogLine cLogLine = new() - { - LogLine = line - }; - - Column[] columns = new Column[8] - { - new() {FullValue = "", Parent = cLogLine}, - new() {FullValue = "", Parent = cLogLine}, - new() {FullValue = "", Parent = cLogLine}, - new() {FullValue = "", Parent = cLogLine}, - new() {FullValue = "", Parent = cLogLine}, - new() {FullValue = "", Parent = cLogLine}, - new() {FullValue = "", Parent = cLogLine}, - new() {FullValue = "", Parent = cLogLine} - }; - - cLogLine.ColumnValues = columns.Select(a => a as IColumn).ToArray(); - - string temp = line.FullLine; - if (temp.Length > 1024) + Match match = lineRegex.Match(temp); + GroupCollection groups = match.Groups; + if (groups.Count == 10) { - // spam - temp = temp.Substring(0, 1024); - columns[3].FullValue = temp; - return cLogLine; - } - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - // anon-212-34-174-126.suchen.de - - [08/Mar/2008:00:41:10 +0100] "GET /wiki/index.php?title=Bild:Poster_small.jpg&printable=yes&printable=yes HTTP/1.1" 304 0 "http://www.captain-kloppi.de/wiki/index.php?title=Bild:Poster_small.jpg&printable=yes" "gonzo1[P] +http://www.suchen.de/faq.html" - - if (lineRegex.IsMatch(temp)) - { - Match match = lineRegex.Match(temp); - GroupCollection groups = match.Groups; - if (groups.Count == 10) + columns[0].FullValue = groups[1].Value; + columns[1].FullValue = groups[3].Value; + columns[3].FullValue = groups[5].Value; + columns[4].FullValue = groups[6].Value; + columns[5].FullValue = groups[7].Value; + columns[6].FullValue = groups[8].Value; + columns[7].FullValue = groups[9].Value; + + var dateTimeStr = groups[4].Value.Substring(1, 26); + + // dirty probing of date/time format (much faster than DateTime.ParseExact() + if (dateTimeStr[2] == '/' && dateTimeStr[6] == '/' && dateTimeStr[11] == ':') { - columns[0].FullValue = groups[1].Value; - columns[1].FullValue = groups[3].Value; - columns[3].FullValue = groups[5].Value; - columns[4].FullValue = groups[6].Value; - columns[5].FullValue = groups[7].Value; - columns[6].FullValue = groups[8].Value; - columns[7].FullValue = groups[9].Value; - - string dateTimeStr = groups[4].Value.Substring(1, 26); - - // dirty probing of date/time format (much faster than DateTime.ParseExact() - if (dateTimeStr[2] == '/' && dateTimeStr[6] == '/' && dateTimeStr[11] == ':') + if (timeOffset != 0) { - if (timeOffset != 0) + try { - try - { - DateTime dateTime = DateTime.ParseExact(dateTimeStr, "dd/MMM/yyyy:HH:mm:ss zzz", - new CultureInfo("en-US")); - dateTime = dateTime.Add(new TimeSpan(0, 0, 0, 0, timeOffset)); - string newDate = dateTime.ToString("dd/MMM/yyyy:HH:mm:ss zzz", - new CultureInfo("en-US")); - columns[2].FullValue = newDate; - } - catch (Exception) - { - columns[2].FullValue = "n/a"; - } + var dateTime = DateTime.ParseExact(dateTimeStr, "dd/MMM/yyyy:HH:mm:ss zzz", + new CultureInfo("en-US")); + dateTime = dateTime.Add(new TimeSpan(0, 0, 0, 0, timeOffset)); + var newDate = dateTime.ToString("dd/MMM/yyyy:HH:mm:ss zzz", + new CultureInfo("en-US")); + columns[2].FullValue = newDate; } - else + catch (Exception) { - columns[2].FullValue = dateTimeStr; + columns[2].FullValue = "n/a"; } } else @@ -185,15 +180,19 @@ public IColumnizedLogLine SplitLine(LogExpert.ILogLineColumnizerCallback callbac columns[2].FullValue = dateTimeStr; } } + else + { + columns[2].FullValue = dateTimeStr; + } } - else - { - columns[3].FullValue = temp; - } - - return cLogLine; + } + else + { + columns[3].FullValue = temp; } - #endregion + return cLogLine; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Columnizer/ColumnizerPicker.cs b/src/LogExpert.Core/Classes/Columnizer/ColumnizerPicker.cs index abb616a0..33cf2ac8 100644 --- a/src/LogExpert.Core/Classes/Columnizer/ColumnizerPicker.cs +++ b/src/LogExpert.Core/Classes/Columnizer/ColumnizerPicker.cs @@ -2,142 +2,141 @@ using System.Reflection; -namespace LogExpert.Core.Classes.Columnizer +namespace LogExpert.Core.Classes.Columnizer; + +public class ColumnizerPicker { - public class ColumnizerPicker + public static ILogLineColumnizer FindColumnizerByName(string name, IList list) { - public static ILogLineColumnizer FindColumnizerByName(string name, IList list) + foreach (ILogLineColumnizer columnizer in list) { - foreach (ILogLineColumnizer columnizer in list) + if (columnizer.GetName().Equals(name)) { - if (columnizer.GetName().Equals(name)) - { - return columnizer; - } + return columnizer; } - return null; } + return null; + } - public static ILogLineColumnizer DecideColumnizerByName(string name, IList list) + public static ILogLineColumnizer DecideColumnizerByName(string name, IList list) + { + foreach (ILogLineColumnizer columnizer in list) { - foreach (ILogLineColumnizer columnizer in list) + if (columnizer.GetName().Equals(name)) { - if (columnizer.GetName().Equals(name)) - { - return columnizer; - } + return columnizer; } - - return FindColumnizer(null, null, list); } - public static ILogLineColumnizer CloneColumnizer(ILogLineColumnizer columnizer, string directory) - { - if (columnizer == null) - { - return null; - } - ConstructorInfo cti = columnizer.GetType().GetConstructor(Type.EmptyTypes); - - if (cti != null) - { - object o = cti.Invoke([]); + return FindColumnizer(null, null, list); + } - if (o is IColumnizerConfigurator configurator) - { - configurator.LoadConfig(directory); - } - return (ILogLineColumnizer)o; - } + public static ILogLineColumnizer CloneColumnizer(ILogLineColumnizer columnizer, string directory) + { + if (columnizer == null) + { return null; } + ConstructorInfo cti = columnizer.GetType().GetConstructor(Type.EmptyTypes); - /// - /// This method implemented the "auto columnizer" feature. - /// This method should be called after each columnizer is changed to update the columizer. - /// - /// - /// - /// - /// - public static ILogLineColumnizer FindReplacementForAutoColumnizer(string fileName, - IAutoLogLineColumnizerCallback logFileReader, - ILogLineColumnizer logLineColumnizer, - IList list) + if (cti != null) { - if (logLineColumnizer == null || logLineColumnizer.GetName() == "Auto Columnizer") + var o = cti.Invoke([]); + + if (o is IColumnizerConfigurator configurator) { - return FindColumnizer(fileName, logFileReader, list); + configurator.LoadConfig(directory); } - return logLineColumnizer; + return (ILogLineColumnizer)o; } + return null; + } - public static ILogLineColumnizer FindBetterColumnizer(string fileName, - IAutoLogLineColumnizerCallback logFileReader, - ILogLineColumnizer logLineColumnizer, - IList list) + /// + /// This method implemented the "auto columnizer" feature. + /// This method should be called after each columnizer is changed to update the columizer. + /// + /// + /// + /// + /// + public static ILogLineColumnizer FindReplacementForAutoColumnizer(string fileName, + IAutoLogLineColumnizerCallback logFileReader, + ILogLineColumnizer logLineColumnizer, + IList list) + { + if (logLineColumnizer == null || logLineColumnizer.GetName() == "Auto Columnizer") { - var newColumnizer = FindColumnizer(fileName, logFileReader, list); + return FindColumnizer(fileName, logFileReader, list); + } + return logLineColumnizer; + } - if (newColumnizer.GetType().Equals(logLineColumnizer.GetType())) - { - return null; - } - return newColumnizer; + public static ILogLineColumnizer FindBetterColumnizer(string fileName, + IAutoLogLineColumnizerCallback logFileReader, + ILogLineColumnizer logLineColumnizer, + IList list) + { + var newColumnizer = FindColumnizer(fileName, logFileReader, list); + + if (newColumnizer.GetType().Equals(logLineColumnizer.GetType())) + { + return null; } + return newColumnizer; + } - /// - /// This method will search all registered columnizer and return one according to the priority that returned - /// by the each columnizer. - /// - /// - /// - /// - public static ILogLineColumnizer FindColumnizer(string fileName, IAutoLogLineColumnizerCallback logFileReader, IList list) + /// + /// This method will search all registered columnizer and return one according to the priority that returned + /// by the each columnizer. + /// + /// + /// + /// + public static ILogLineColumnizer FindColumnizer(string fileName, IAutoLogLineColumnizerCallback logFileReader, IList list) + { + if (string.IsNullOrEmpty(fileName)) { - if (string.IsNullOrEmpty(fileName)) - { - return new DefaultLogfileColumnizer(); - } + return new DefaultLogfileColumnizer(); + } - List loglines = []; + List loglines = []; - if (logFileReader != null) - { - loglines = - [ - // Sampling a few lines to select the correct columnizer - logFileReader.GetLogLine(0), - logFileReader.GetLogLine(1), - logFileReader.GetLogLine(2), - logFileReader.GetLogLine(3), - logFileReader.GetLogLine(4), - logFileReader.GetLogLine(5), - logFileReader.GetLogLine(25), - logFileReader.GetLogLine(100), - logFileReader.GetLogLine(200), - logFileReader.GetLogLine(400) - ]; - } + if (logFileReader != null) + { + loglines = + [ + // Sampling a few lines to select the correct columnizer + logFileReader.GetLogLine(0), + logFileReader.GetLogLine(1), + logFileReader.GetLogLine(2), + logFileReader.GetLogLine(3), + logFileReader.GetLogLine(4), + logFileReader.GetLogLine(5), + logFileReader.GetLogLine(25), + logFileReader.GetLogLine(100), + logFileReader.GetLogLine(200), + logFileReader.GetLogLine(400) + ]; + } - var registeredColumnizer = list; + var registeredColumnizer = list; - List> priorityListOfColumnizers = []; + List> priorityListOfColumnizers = []; - foreach (ILogLineColumnizer logLineColumnizer in registeredColumnizer) + foreach (ILogLineColumnizer logLineColumnizer in registeredColumnizer) + { + Priority priority = default; + if (logLineColumnizer is IColumnizerPriority columnizerPriority) { - Priority priority = default; - if (logLineColumnizer is IColumnizerPriority columnizerPriority) - { - priority = columnizerPriority.GetPriority(fileName, loglines); - } - - priorityListOfColumnizers.Add(new Tuple(priority, logLineColumnizer)); + priority = columnizerPriority.GetPriority(fileName, loglines); } - ILogLineColumnizer lineColumnizer = priorityListOfColumnizers.OrderByDescending(a => a.Item1).Select(a => a.Item2).First(); - - return lineColumnizer; + priorityListOfColumnizers.Add(new Tuple(priority, logLineColumnizer)); } + + ILogLineColumnizer lineColumnizer = priorityListOfColumnizers.OrderByDescending(a => a.Item1).Select(a => a.Item2).First(); + + return lineColumnizer; } } diff --git a/src/LogExpert.Core/Classes/Columnizer/SquareBracketColumnizer.cs b/src/LogExpert.Core/Classes/Columnizer/SquareBracketColumnizer.cs index 9ca62371..769cf4c4 100644 --- a/src/LogExpert.Core/Classes/Columnizer/SquareBracketColumnizer.cs +++ b/src/LogExpert.Core/Classes/Columnizer/SquareBracketColumnizer.cs @@ -2,318 +2,317 @@ using static LogExpert.Core.Classes.Columnizer.TimeFormatDeterminer; -namespace LogExpert.Core.Classes.Columnizer +namespace LogExpert.Core.Classes.Columnizer; + +public class SquareBracketColumnizer : ILogLineColumnizer, IColumnizerPriority { - public class SquareBracketColumnizer : ILogLineColumnizer, IColumnizerPriority - { - #region ILogLineColumnizer implementation + #region ILogLineColumnizer implementation + + protected int timeOffset; + private TimeFormatDeterminer _timeFormatDeterminer = new(); - protected int timeOffset = 0; - private TimeFormatDeterminer _timeFormatDeterminer = new(); + // TODO: need preparing this columnizer with sample log lines before use it. + private int _columnCount = 5; + private bool _isTimeExists; - // TODO: need preparing this columnizer with sample log lines before use it. - private int _columnCount = 5; - private bool _isTimeExists = false; + public SquareBracketColumnizer () + { + } - public SquareBracketColumnizer () + public SquareBracketColumnizer (int columnCount, bool isTimeExists) : this() + { + // Add message column + _columnCount = columnCount + 1; + _isTimeExists = isTimeExists; + if (_isTimeExists) { + // Time and date + _columnCount += 2; } + } + + public bool IsTimeshiftImplemented () + { + return true; + } - public SquareBracketColumnizer (int columnCount, bool isTimeExists) : this() + public void SetTimeOffset (int msecOffset) + { + timeOffset = msecOffset; + } + + public int GetTimeOffset () + { + return timeOffset; + } + + public DateTime GetTimestamp (LogExpert.ILogLineColumnizerCallback callback, ILogLine line) + { + IColumnizedLogLine cols = SplitLine(callback, line); + if (cols == null || cols.ColumnValues == null || cols.ColumnValues.Length < 2) { - // Add message column - _columnCount = columnCount + 1; - _isTimeExists = isTimeExists; - if (_isTimeExists) - { - // Time and date - _columnCount += 2; - } + return DateTime.MinValue; } - public bool IsTimeshiftImplemented () + if (cols.ColumnValues[0].FullValue.Length == 0 || cols.ColumnValues[1].FullValue.Length == 0) { - return true; + return DateTime.MinValue; } - public void SetTimeOffset (int msecOffset) + FormatInfo formatInfo = _timeFormatDeterminer.DetermineDateTimeFormatInfo(line.FullLine); + if (formatInfo == null) { - timeOffset = msecOffset; + return DateTime.MinValue; } - public int GetTimeOffset () + try { - return timeOffset; + var dateTime = DateTime.ParseExact( + cols.ColumnValues[0].FullValue + " " + cols.ColumnValues[1].FullValue, formatInfo.DateTimeFormat, + formatInfo.CultureInfo); + return dateTime; } - - public DateTime GetTimestamp (LogExpert.ILogLineColumnizerCallback callback, ILogLine line) + catch (Exception) { - IColumnizedLogLine cols = SplitLine(callback, line); - if (cols == null || cols.ColumnValues == null || cols.ColumnValues.Length < 2) - { - return DateTime.MinValue; - } - - if (cols.ColumnValues[0].FullValue.Length == 0 || cols.ColumnValues[1].FullValue.Length == 0) - { - return DateTime.MinValue; - } - - FormatInfo formatInfo = _timeFormatDeterminer.DetermineDateTimeFormatInfo(line.FullLine); - if (formatInfo == null) - { - return DateTime.MinValue; - } - - try - { - DateTime dateTime = DateTime.ParseExact( - cols.ColumnValues[0].FullValue + " " + cols.ColumnValues[1].FullValue, formatInfo.DateTimeFormat, - formatInfo.CultureInfo); - return dateTime; - } - catch (Exception) - { - return DateTime.MinValue; - } + return DateTime.MinValue; } + } - public void PushValue (LogExpert.ILogLineColumnizerCallback callback, int column, string value, string oldValue) + public void PushValue (LogExpert.ILogLineColumnizerCallback callback, int column, string value, string oldValue) + { + if (column == 1) { - if (column == 1) + try { - try - { - FormatInfo formatInfo = _timeFormatDeterminer.DetermineTimeFormatInfo(oldValue); - if (formatInfo == null) - { - return; - } - - DateTime newDateTime = DateTime.ParseExact(value, formatInfo.TimeFormat, formatInfo.CultureInfo); - DateTime oldDateTime = DateTime.ParseExact(oldValue, formatInfo.TimeFormat, formatInfo.CultureInfo); - long mSecsOld = oldDateTime.Ticks / TimeSpan.TicksPerMillisecond; - long mSecsNew = newDateTime.Ticks / TimeSpan.TicksPerMillisecond; - timeOffset = (int)(mSecsNew - mSecsOld); - } - catch (FormatException) + FormatInfo formatInfo = _timeFormatDeterminer.DetermineTimeFormatInfo(oldValue); + if (formatInfo == null) { + return; } + + var newDateTime = DateTime.ParseExact(value, formatInfo.TimeFormat, formatInfo.CultureInfo); + var oldDateTime = DateTime.ParseExact(oldValue, formatInfo.TimeFormat, formatInfo.CultureInfo); + var mSecsOld = oldDateTime.Ticks / TimeSpan.TicksPerMillisecond; + var mSecsNew = newDateTime.Ticks / TimeSpan.TicksPerMillisecond; + timeOffset = (int)(mSecsNew - mSecsOld); + } + catch (FormatException) + { } } + } + + public string GetName () + { + return "Square Bracket Columnizer"; + } + + public string GetDescription () + { + return "Splits every line into n fields: Date, Time and the rest of the log message"; + } - public string GetName () + public int GetColumnCount () + { + return _columnCount; + } + + public string[] GetColumnNames () + { + var columnNames = new List(GetColumnCount()); + if (_isTimeExists) { - return "Square Bracket Columnizer"; + columnNames.Add("Date"); + columnNames.Add("Time"); } - public string GetDescription () + // TODO: Make this configurable. + if (GetColumnCount() > 3) { - return "Splits every line into n fields: Date, Time and the rest of the log message"; + columnNames.Add("Level"); } - public int GetColumnCount () + if (GetColumnCount() > 4) { - return _columnCount; + columnNames.Add("Source"); } - public string[] GetColumnNames () + // Last column is the message + columnNames.Add("Message"); + var i = 1; + while (columnNames.Count < GetColumnCount()) { - var columnNames = new List(GetColumnCount()); - if (_isTimeExists) - { - columnNames.Add("Date"); - columnNames.Add("Time"); - } - - // TODO: Make this configurable. - if (GetColumnCount() > 3) - { - columnNames.Add("Level"); - } - - if (GetColumnCount() > 4) - { - columnNames.Add("Source"); - } + columnNames.Insert(columnNames.Count - 1, "Source" + i++.ToString()); + } - // Last column is the message - columnNames.Add("Message"); - int i = 1; - while (columnNames.Count < GetColumnCount()) - { - columnNames.Insert(columnNames.Count - 1, "Source" + i++.ToString()); - } + return columnNames.ToArray(); + } - return columnNames.ToArray(); - } + public IColumnizedLogLine SplitLine (LogExpert.ILogLineColumnizerCallback callback, ILogLine line) + { + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + // 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 + // 03.01.2008 14:48:00.066 - public IColumnizedLogLine SplitLine (LogExpert.ILogLineColumnizerCallback callback, ILogLine line) + ColumnizedLogLine clogLine = new() { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - // 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 - // 03.01.2008 14:48:00.066 + LogLine = line + }; - ColumnizedLogLine clogLine = new() - { - LogLine = line - }; - - Column[] columns = new Column[] - { - new() {FullValue = "", Parent = clogLine}, - new() {FullValue = "", Parent = clogLine}, - new() {FullValue = "", Parent = clogLine}, - }; + var columns = new Column[] + { + new() {FullValue = "", Parent = clogLine}, + new() {FullValue = "", Parent = clogLine}, + new() {FullValue = "", Parent = clogLine}, + }; - string temp = line.FullLine; + var temp = line.FullLine; - if (temp.Length < 3) - { - columns[2].FullValue = temp; - return clogLine; - } + if (temp.Length < 3) + { + columns[2].FullValue = temp; + return clogLine; + } - FormatInfo formatInfo = _timeFormatDeterminer.DetermineDateTimeFormatInfo(line.FullLine); - if (formatInfo == null) - { - columns[2].FullValue = temp; - SquareSplit(ref columns, temp, 0, 0, 0, clogLine); - } - else + FormatInfo formatInfo = _timeFormatDeterminer.DetermineDateTimeFormatInfo(line.FullLine); + if (formatInfo == null) + { + columns[2].FullValue = temp; + SquareSplit(ref columns, temp, 0, 0, 0, clogLine); + } + else + { + var endPos = formatInfo.DateTimeFormat.Length; + var timeLen = formatInfo.TimeFormat.Length; + var dateLen = formatInfo.DateFormat.Length; + try { - int endPos = formatInfo.DateTimeFormat.Length; - int timeLen = formatInfo.TimeFormat.Length; - int dateLen = formatInfo.DateFormat.Length; - try + if (timeOffset != 0) { - if (timeOffset != 0) - { - DateTime dateTime = DateTime.ParseExact(temp.Substring(0, endPos), formatInfo.DateTimeFormat, - formatInfo.CultureInfo); - dateTime = dateTime.Add(new TimeSpan(0, 0, 0, 0, timeOffset)); - string newDate = dateTime.ToString(formatInfo.DateTimeFormat, formatInfo.CultureInfo); - - SquareSplit(ref columns, newDate, dateLen, timeLen, endPos, clogLine); - } - else - { - SquareSplit(ref columns, temp, dateLen, timeLen, endPos, clogLine); - } + var dateTime = DateTime.ParseExact(temp.Substring(0, endPos), formatInfo.DateTimeFormat, + formatInfo.CultureInfo); + dateTime = dateTime.Add(new TimeSpan(0, 0, 0, 0, timeOffset)); + var newDate = dateTime.ToString(formatInfo.DateTimeFormat, formatInfo.CultureInfo); + + SquareSplit(ref columns, newDate, dateLen, timeLen, endPos, clogLine); } - catch (Exception) + else { - columns[0].FullValue = "n/a"; - columns[1].FullValue = "n/a"; - columns[2].FullValue = temp; + SquareSplit(ref columns, temp, dateLen, timeLen, endPos, clogLine); } } - - clogLine.ColumnValues = columns.Select(a => a as IColumn).ToArray(); - - return clogLine; - } - - void SquareSplit (ref Column[] columns, string line, int dateLen, int timeLen, int dateTimeEndPos, ColumnizedLogLine clogLine) - { - List columnList = []; - int restColumn = _columnCount; - if (_isTimeExists) + catch (Exception) { - columnList.Add(new Column { FullValue = line.Substring(0, dateLen), Parent = clogLine }); - columnList.Add(new Column { FullValue = line.Substring(dateLen + 1, timeLen), Parent = clogLine }); - restColumn -= 2; + columns[0].FullValue = "n/a"; + columns[1].FullValue = "n/a"; + columns[2].FullValue = temp; } + } - int nextPos = dateTimeEndPos; + clogLine.ColumnValues = columns.Select(a => a as IColumn).ToArray(); - string rest = line; + return clogLine; + } - for (int i = 0; i < restColumn; i++) - { - rest = rest.Substring(nextPos); - //var fullValue = rest.Substring(0, rest.IndexOf(']')).TrimStart(new char[] {' '}).TrimEnd(new char[] { ' ' }); - var trimmed = rest.TrimStart(new char[] { ' ' }); - if (string.IsNullOrEmpty(trimmed) || trimmed[0] != '[' || rest.IndexOf(']') < 0 || i == restColumn - 1) - { - columnList.Add(new Column { FullValue = rest, Parent = clogLine }); - break; - } + void SquareSplit (ref Column[] columns, string line, int dateLen, int timeLen, int dateTimeEndPos, ColumnizedLogLine clogLine) + { + List columnList = []; + var restColumn = _columnCount; + if (_isTimeExists) + { + columnList.Add(new Column { FullValue = line.Substring(0, dateLen), Parent = clogLine }); + columnList.Add(new Column { FullValue = line.Substring(dateLen + 1, timeLen), Parent = clogLine }); + restColumn -= 2; + } - nextPos = rest.IndexOf(']') + 1; - var fullValue = rest.Substring(0, nextPos); - columnList.Add(new Column { FullValue = fullValue, Parent = clogLine }); - } + var nextPos = dateTimeEndPos; + + var rest = line; - while (columnList.Count < _columnCount) + for (var i = 0; i < restColumn; i++) + { + rest = rest.Substring(nextPos); + //var fullValue = rest.Substring(0, rest.IndexOf(']')).TrimStart(new char[] {' '}).TrimEnd(new char[] { ' ' }); + var trimmed = rest.TrimStart([' ']); + if (string.IsNullOrEmpty(trimmed) || trimmed[0] != '[' || rest.IndexOf(']') < 0 || i == restColumn - 1) { - columnList.Insert(columnList.Count - 1, new Column { FullValue = "", Parent = clogLine }); + columnList.Add(new Column { FullValue = rest, Parent = clogLine }); + break; } - columns = columnList.ToArray(); + nextPos = rest.IndexOf(']') + 1; + var fullValue = rest.Substring(0, nextPos); + columnList.Add(new Column { FullValue = fullValue, Parent = clogLine }); } - public Priority GetPriority (string fileName, IEnumerable samples) + while (columnList.Count < _columnCount) { - Priority result = Priority.NotSupport; - TimeFormatDeterminer timeDeterminer = new(); - int timeStampExistsCount = 0; - int bracketsExistsCount = 0; - int maxBracketNumbers = 1; - - foreach (var logline in samples) - { - string line = logline?.FullLine; - if (string.IsNullOrEmpty(line)) - { - continue; - } + columnList.Insert(columnList.Count - 1, new Column { FullValue = "", Parent = clogLine }); + } - int bracketNumbers = 1; - if (null != timeDeterminer.DetermineDateTimeFormatInfo(line)) - { - timeStampExistsCount++; - } - else - { - timeStampExistsCount--; - } + columns = columnList.ToArray(); + } - string noSpaceLine = line.Replace(" ", string.Empty); - if (noSpaceLine.IndexOf('[') >= 0 && noSpaceLine.IndexOf(']') >= 0 - && noSpaceLine.IndexOf('[') < noSpaceLine.IndexOf(']')) - { - bracketNumbers += Regex.Matches(noSpaceLine, @"\]\[").Count; - bracketsExistsCount++; - } - else - { - bracketsExistsCount--; - } + public Priority GetPriority (string fileName, IEnumerable samples) + { + Priority result = Priority.NotSupport; + TimeFormatDeterminer timeDeterminer = new(); + var timeStampExistsCount = 0; + var bracketsExistsCount = 0; + var maxBracketNumbers = 1; - maxBracketNumbers = Math.Max(bracketNumbers, maxBracketNumbers); + foreach (var logline in samples) + { + var line = logline?.FullLine; + if (string.IsNullOrEmpty(line)) + { + continue; } - // Add message - _columnCount = maxBracketNumbers + 1; - _isTimeExists = timeStampExistsCount > 0; - if (_isTimeExists) + var bracketNumbers = 1; + if (null != timeDeterminer.DetermineDateTimeFormatInfo(line)) { - _columnCount += 2; + timeStampExistsCount++; + } + else + { + timeStampExistsCount--; } - if (maxBracketNumbers > 1) + var noSpaceLine = line.Replace(" ", string.Empty); + if (noSpaceLine.IndexOf('[') >= 0 && noSpaceLine.IndexOf(']') >= 0 + && noSpaceLine.IndexOf('[') < noSpaceLine.IndexOf(']')) { - result = Priority.WellSupport; - if (bracketsExistsCount > 0) - { - result = Priority.PerfectlySupport; - } + bracketNumbers += Regex.Matches(noSpaceLine, @"\]\[").Count; + bracketsExistsCount++; + } + else + { + bracketsExistsCount--; } - return result; + maxBracketNumbers = Math.Max(bracketNumbers, maxBracketNumbers); } - #endregion + // Add message + _columnCount = maxBracketNumbers + 1; + _isTimeExists = timeStampExistsCount > 0; + if (_isTimeExists) + { + _columnCount += 2; + } + + if (maxBracketNumbers > 1) + { + result = Priority.WellSupport; + if (bracketsExistsCount > 0) + { + result = Priority.PerfectlySupport; + } + } + + return result; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Columnizer/TimeFormatDeterminer.cs b/src/LogExpert.Core/Classes/Columnizer/TimeFormatDeterminer.cs index 77da6cbd..cf438dc1 100644 --- a/src/LogExpert.Core/Classes/Columnizer/TimeFormatDeterminer.cs +++ b/src/LogExpert.Core/Classes/Columnizer/TimeFormatDeterminer.cs @@ -1,242 +1,238 @@ using System.Globalization; -namespace LogExpert.Core.Classes.Columnizer +namespace LogExpert.Core.Classes.Columnizer; + +internal class TimeFormatDeterminer { - internal class TimeFormatDeterminer + #region FormatInfo helper class + + public class FormatInfo { - #region FormatInfo helper class + #region cTor - public class FormatInfo + public FormatInfo(string dateFormat, string timeFormat, CultureInfo cultureInfo) { - #region cTor + DateFormat = dateFormat; + TimeFormat = timeFormat; + CultureInfo = cultureInfo; + } - public FormatInfo(string dateFormat, string timeFormat, CultureInfo cultureInfo) - { - DateFormat = dateFormat; - TimeFormat = timeFormat; - CultureInfo = cultureInfo; - } + #endregion - #endregion + #region Properties - #region Properties + public string DateFormat { get; } - public string DateFormat { get; } + public string TimeFormat { get; } - public string TimeFormat { get; } + public CultureInfo CultureInfo { get; } - public CultureInfo CultureInfo { get; } + public string DateTimeFormat => DateFormat + " " + TimeFormat; - public string DateTimeFormat - { - get { return DateFormat + " " + TimeFormat; } - } + public bool IgnoreFirstChar { get; set; } - public bool IgnoreFirstChar { get; set; } + #endregion + } - #endregion + #endregion + + protected FormatInfo formatInfo1 = new("dd.MM.yyyy", "HH:mm:ss.fff", new CultureInfo("de-DE")); + protected FormatInfo formatInfo2 = new("dd.MM.yyyy", "HH:mm:ss", new CultureInfo("de-DE")); + protected FormatInfo formatInfo3 = new("yyyy/MM/dd", "HH:mm:ss.fff", new CultureInfo("en-US")); + protected FormatInfo formatInfo4 = new("yyyy/MM/dd", "HH:mm:ss", new CultureInfo("en-US")); + protected FormatInfo formatInfo5 = new("yyyy.MM.dd", "HH:mm:ss.fff", new CultureInfo("de-DE")); + protected FormatInfo formatInfo6 = new("yyyy.MM.dd", "HH:mm:ss", new CultureInfo("de-DE")); + protected FormatInfo formatInfo7 = new("dd.MM.yyyy", "HH:mm:ss,fff", new CultureInfo("de-DE")); + protected FormatInfo formatInfo8 = new("yyyy/MM/dd", "HH:mm:ss,fff", new CultureInfo("en-US")); + protected FormatInfo formatInfo9 = new("yyyy.MM.dd", "HH:mm:ss,fff", new CultureInfo("de-DE")); + protected FormatInfo formatInfo10 = new("yyyy-MM-dd", "HH:mm:ss.fff", new CultureInfo("en-US")); + protected FormatInfo formatInfo11 = new("yyyy-MM-dd", "HH:mm:ss,fff", new CultureInfo("en-US")); + protected FormatInfo formatInfo12 = new("yyyy-MM-dd", "HH:mm:ss", new CultureInfo("en-US")); + protected FormatInfo formatInfo13 = new("dd MMM yyyy", "HH:mm:ss,fff", new CultureInfo("de-DE")); + protected FormatInfo formatInfo14 = new("dd MMM yyyy", "HH:mm:ss.fff", new CultureInfo("de-DE")); + protected FormatInfo formatInfo15 = new("dd MMM yyyy", "HH:mm:ss", new CultureInfo("de-DE")); + protected FormatInfo formatInfo16 = new("dd.MM.yy", "HH:mm:ss.fff", new CultureInfo("de-DE")); + protected FormatInfo formatInfo17 = new("yyyy-MM-dd", "HH:mm:ss:ffff", new CultureInfo("en-US")); + protected FormatInfo formatInfo18 = new("dd/MM/yyyy", "HH:mm:ss.fff", new CultureInfo("en-US")); + protected FormatInfo formatInfo19 = new("dd/MM/yyyy", "HH:mm:ss:fff", new CultureInfo("en-US")); + protected FormatInfo formatInfo20 = new("yyyy-MM-dd", "HH:mm:ss.ffff", new CultureInfo("en-US")); + protected FormatInfo formatInfo21 = new("yyyy-MM-dd", "HH:mm:ss,ffff", new CultureInfo("en-US")); + + + public FormatInfo DetermineDateTimeFormatInfo(string line) + { + if (line.Length < 21) + { + return null; } - #endregion + var temp = line; + var ignoreFirst = false; - protected FormatInfo formatInfo1 = new("dd.MM.yyyy", "HH:mm:ss.fff", new CultureInfo("de-DE")); - protected FormatInfo formatInfo2 = new("dd.MM.yyyy", "HH:mm:ss", new CultureInfo("de-DE")); - protected FormatInfo formatInfo3 = new("yyyy/MM/dd", "HH:mm:ss.fff", new CultureInfo("en-US")); - protected FormatInfo formatInfo4 = new("yyyy/MM/dd", "HH:mm:ss", new CultureInfo("en-US")); - protected FormatInfo formatInfo5 = new("yyyy.MM.dd", "HH:mm:ss.fff", new CultureInfo("de-DE")); - protected FormatInfo formatInfo6 = new("yyyy.MM.dd", "HH:mm:ss", new CultureInfo("de-DE")); - protected FormatInfo formatInfo7 = new("dd.MM.yyyy", "HH:mm:ss,fff", new CultureInfo("de-DE")); - protected FormatInfo formatInfo8 = new("yyyy/MM/dd", "HH:mm:ss,fff", new CultureInfo("en-US")); - protected FormatInfo formatInfo9 = new("yyyy.MM.dd", "HH:mm:ss,fff", new CultureInfo("de-DE")); - protected FormatInfo formatInfo10 = new("yyyy-MM-dd", "HH:mm:ss.fff", new CultureInfo("en-US")); - protected FormatInfo formatInfo11 = new("yyyy-MM-dd", "HH:mm:ss,fff", new CultureInfo("en-US")); - protected FormatInfo formatInfo12 = new("yyyy-MM-dd", "HH:mm:ss", new CultureInfo("en-US")); - protected FormatInfo formatInfo13 = new("dd MMM yyyy", "HH:mm:ss,fff", new CultureInfo("de-DE")); - protected FormatInfo formatInfo14 = new("dd MMM yyyy", "HH:mm:ss.fff", new CultureInfo("de-DE")); - protected FormatInfo formatInfo15 = new("dd MMM yyyy", "HH:mm:ss", new CultureInfo("de-DE")); - protected FormatInfo formatInfo16 = new("dd.MM.yy", "HH:mm:ss.fff", new CultureInfo("de-DE")); - protected FormatInfo formatInfo17 = new("yyyy-MM-dd", "HH:mm:ss:ffff", new CultureInfo("en-US")); - protected FormatInfo formatInfo18 = new("dd/MM/yyyy", "HH:mm:ss.fff", new CultureInfo("en-US")); - protected FormatInfo formatInfo19 = new("dd/MM/yyyy", "HH:mm:ss:fff", new CultureInfo("en-US")); - protected FormatInfo formatInfo20 = new("yyyy-MM-dd", "HH:mm:ss.ffff", new CultureInfo("en-US")); - protected FormatInfo formatInfo21 = new("yyyy-MM-dd", "HH:mm:ss,ffff", new CultureInfo("en-US")); - - - public FormatInfo DetermineDateTimeFormatInfo(string line) + // determine if string starts with bracket and remove it + if (temp[0] == '[' || temp[0] == '(' || temp[0] == '{') { - if (line.Length < 21) - { - return null; - } + temp = temp.Substring(1); + ignoreFirst = true; - string temp = line; - bool ignoreFirst = false; + } - // determine if string starts with bracket and remove it - if (temp[0] == '[' || temp[0] == '(' || temp[0] == '{') + // dirty hardcoded probing of date/time format (much faster than DateTime.ParseExact() + if (temp[2] == '.' && temp[5] == '.' && temp[13] == ':' && temp[16] == ':') + { + if (temp[19] == '.') { - temp = temp.Substring(1); - ignoreFirst = true; - + formatInfo1.IgnoreFirstChar = ignoreFirst; + return formatInfo1; } - - // dirty hardcoded probing of date/time format (much faster than DateTime.ParseExact() - if (temp[2] == '.' && temp[5] == '.' && temp[13] == ':' && temp[16] == ':') + else if (temp[19] == ',') { - if (temp[19] == '.') - { - formatInfo1.IgnoreFirstChar = ignoreFirst; - return formatInfo1; - } - else if (temp[19] == ',') - { - formatInfo7.IgnoreFirstChar = ignoreFirst; - return formatInfo7; - } - else - { - formatInfo2.IgnoreFirstChar = ignoreFirst; - return formatInfo2; - } + formatInfo7.IgnoreFirstChar = ignoreFirst; + return formatInfo7; } - else if (temp[2] == '/' && temp[5] == '/' && temp[13] == ':' && temp[16] == ':') + else { - if (temp[19] == '.') - { - formatInfo18.IgnoreFirstChar = ignoreFirst; - return formatInfo18; - } - else if (temp[19] == ':') - { - formatInfo19.IgnoreFirstChar = ignoreFirst; - return formatInfo19; - } + formatInfo2.IgnoreFirstChar = ignoreFirst; + return formatInfo2; } - else if (temp[4] == '/' && temp[7] == '/' && temp[13] == ':' && temp[16] == ':') + } + else if (temp[2] == '/' && temp[5] == '/' && temp[13] == ':' && temp[16] == ':') + { + if (temp[19] == '.') { - if (temp[19] == '.') - { - formatInfo3.IgnoreFirstChar = ignoreFirst; - return formatInfo3; - } - else if (temp[19] == ',') - { - formatInfo8.IgnoreFirstChar = ignoreFirst; - return formatInfo8; - } - else - { - formatInfo4.IgnoreFirstChar = ignoreFirst; - return formatInfo4; - } + formatInfo18.IgnoreFirstChar = ignoreFirst; + return formatInfo18; } - else if (temp[4] == '.' && temp[7] == '.' && temp[13] == ':' && temp[16] == ':') + else if (temp[19] == ':') { - if (temp[19] == '.') - { - formatInfo5.IgnoreFirstChar = ignoreFirst; - return formatInfo5; - } - else if (temp[19] == ',') - { - formatInfo9.IgnoreFirstChar = ignoreFirst; - return formatInfo9; - } - else - { - formatInfo6.IgnoreFirstChar = ignoreFirst; - return formatInfo6; - } + formatInfo19.IgnoreFirstChar = ignoreFirst; + return formatInfo19; } - else if (temp[4] == '-' && temp[7] == '-' && temp[13] == ':' && temp[16] == ':') + } + else if (temp[4] == '/' && temp[7] == '/' && temp[13] == ':' && temp[16] == ':') + { + if (temp[19] == '.') { - if (temp[19] == '.') - { - if (temp.Length > 23 && char.IsDigit(temp[23])) - { - formatInfo20.IgnoreFirstChar = ignoreFirst; - return formatInfo20; - } - else - { - formatInfo10.IgnoreFirstChar = ignoreFirst; - return formatInfo10; - } - } - else if (temp[19] == ',') - { - if (temp.Length > 23 && char.IsDigit(temp[23])) - { - formatInfo21.IgnoreFirstChar = ignoreFirst; - return formatInfo21; - } - else - { - formatInfo11.IgnoreFirstChar = ignoreFirst; - return formatInfo11; - } - } - else if (temp[19] == ':') + formatInfo3.IgnoreFirstChar = ignoreFirst; + return formatInfo3; + } + else if (temp[19] == ',') + { + formatInfo8.IgnoreFirstChar = ignoreFirst; + return formatInfo8; + } + else + { + formatInfo4.IgnoreFirstChar = ignoreFirst; + return formatInfo4; + } + } + else if (temp[4] == '.' && temp[7] == '.' && temp[13] == ':' && temp[16] == ':') + { + if (temp[19] == '.') + { + formatInfo5.IgnoreFirstChar = ignoreFirst; + return formatInfo5; + } + else if (temp[19] == ',') + { + formatInfo9.IgnoreFirstChar = ignoreFirst; + return formatInfo9; + } + else + { + formatInfo6.IgnoreFirstChar = ignoreFirst; + return formatInfo6; + } + } + else if (temp[4] == '-' && temp[7] == '-' && temp[13] == ':' && temp[16] == ':') + { + if (temp[19] == '.') + { + if (temp.Length > 23 && char.IsDigit(temp[23])) { - formatInfo17.IgnoreFirstChar = ignoreFirst; - return formatInfo17; + formatInfo20.IgnoreFirstChar = ignoreFirst; + return formatInfo20; } else { - formatInfo12.IgnoreFirstChar = ignoreFirst; - return formatInfo12; + formatInfo10.IgnoreFirstChar = ignoreFirst; + return formatInfo10; } } - else if (temp[2] == ' ' && temp[6] == ' ' && temp[14] == ':' && temp[17] == ':') + else if (temp[19] == ',') { - if (temp[20] == ',') - { - formatInfo13.IgnoreFirstChar = ignoreFirst; - return formatInfo13; - } - else if (temp[20] == '.') + if (temp.Length > 23 && char.IsDigit(temp[23])) { - formatInfo14.IgnoreFirstChar = ignoreFirst; - return formatInfo14; + formatInfo21.IgnoreFirstChar = ignoreFirst; + return formatInfo21; } else { - formatInfo15.IgnoreFirstChar = ignoreFirst; - return formatInfo15; + formatInfo11.IgnoreFirstChar = ignoreFirst; + return formatInfo11; } } - //dd.MM.yy HH:mm:ss.fff - else if (temp[2] == '.' && temp[5] == '.' && temp[11] == ':' && temp[14] == ':' && temp[17] == '.') + else if (temp[19] == ':') { - formatInfo16.IgnoreFirstChar = ignoreFirst; - return formatInfo16; + formatInfo17.IgnoreFirstChar = ignoreFirst; + return formatInfo17; } - - return null; + else + { + formatInfo12.IgnoreFirstChar = ignoreFirst; + return formatInfo12; + } + } + else if (temp[2] == ' ' && temp[6] == ' ' && temp[14] == ':' && temp[17] == ':') + { + if (temp[20] == ',') + { + formatInfo13.IgnoreFirstChar = ignoreFirst; + return formatInfo13; + } + else if (temp[20] == '.') + { + formatInfo14.IgnoreFirstChar = ignoreFirst; + return formatInfo14; + } + else + { + formatInfo15.IgnoreFirstChar = ignoreFirst; + return formatInfo15; + } + } + //dd.MM.yy HH:mm:ss.fff + else if (temp[2] == '.' && temp[5] == '.' && temp[11] == ':' && temp[14] == ':' && temp[17] == '.') + { + formatInfo16.IgnoreFirstChar = ignoreFirst; + return formatInfo16; } - public FormatInfo DetermineTimeFormatInfo(string field) + return null; + } + + public FormatInfo DetermineTimeFormatInfo(string field) + { + // dirty hardcoded probing of time format (much faster than DateTime.ParseExact() + if (field[2] == ':' && field[5] == ':') { - // dirty hardcoded probing of time format (much faster than DateTime.ParseExact() - if (field[2] == ':' && field[5] == ':') + if (field.Length > 8) { - if (field.Length > 8) + if (field[8] == '.') { - if (field[8] == '.') - { - return formatInfo1; - } - else if (field[8] == ',') - { - return formatInfo7; - } + return formatInfo1; } - else + else if (field[8] == ',') { - return formatInfo2; + return formatInfo7; } } - return null; + else + { + return formatInfo2; + } } + return null; } } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Columnizer/TimestampColumnizer.cs b/src/LogExpert.Core/Classes/Columnizer/TimestampColumnizer.cs index fd033f9a..20239ceb 100644 --- a/src/LogExpert.Core/Classes/Columnizer/TimestampColumnizer.cs +++ b/src/LogExpert.Core/Classes/Columnizer/TimestampColumnizer.cs @@ -1,215 +1,214 @@ using static LogExpert.Core.Classes.Columnizer.TimeFormatDeterminer; -namespace LogExpert.Core.Classes.Columnizer +namespace LogExpert.Core.Classes.Columnizer; + +public class TimestampColumnizer : ILogLineColumnizer, IColumnizerPriority { - public class TimestampColumnizer : ILogLineColumnizer, IColumnizerPriority + #region ILogLineColumnizer implementation + + private int timeOffset; + private readonly TimeFormatDeterminer _timeFormatDeterminer = new(); + + public bool IsTimeshiftImplemented () { - #region ILogLineColumnizer implementation + return true; + } - protected int timeOffset = 0; - private TimeFormatDeterminer _timeFormatDeterminer = new(); + public void SetTimeOffset (int msecOffset) + { + timeOffset = msecOffset; + } - public bool IsTimeshiftImplemented() + public int GetTimeOffset () + { + return timeOffset; + } + + + public DateTime GetTimestamp (ILogLineColumnizerCallback callback, ILogLine line) + { + IColumnizedLogLine cols = SplitLine(callback, line); + if (cols == null || cols.ColumnValues == null || cols.ColumnValues.Length < 2) { - return true; + return DateTime.MinValue; } - - public void SetTimeOffset(int msecOffset) + if (cols.ColumnValues[0].FullValue.Length == 0 || cols.ColumnValues[1].FullValue.Length == 0) { - timeOffset = msecOffset; + return DateTime.MinValue; } - - public int GetTimeOffset() + FormatInfo formatInfo = _timeFormatDeterminer.DetermineDateTimeFormatInfo(line.FullLine); + if (formatInfo == null) { - return timeOffset; + return DateTime.MinValue; } - - public DateTime GetTimestamp(LogExpert.ILogLineColumnizerCallback callback, ILogLine line) + try { - IColumnizedLogLine cols = SplitLine(callback, line); - if (cols == null || cols.ColumnValues == null || cols.ColumnValues.Length < 2) - { - return DateTime.MinValue; - } - if (cols.ColumnValues[0].FullValue.Length == 0 || cols.ColumnValues[1].FullValue.Length == 0) - { - return DateTime.MinValue; - } - FormatInfo formatInfo = _timeFormatDeterminer.DetermineDateTimeFormatInfo(line.FullLine); - if (formatInfo == null) - { - return DateTime.MinValue; - } - - try - { - DateTime dateTime = DateTime.ParseExact( - cols.ColumnValues[0].FullValue + " " + cols.ColumnValues[1].FullValue, formatInfo.DateTimeFormat, - formatInfo.CultureInfo); - return dateTime; - } - catch (Exception) - { - return DateTime.MinValue; - } + var dateTime = DateTime.ParseExact( + cols.ColumnValues[0].FullValue + " " + cols.ColumnValues[1].FullValue, formatInfo.DateTimeFormat, + formatInfo.CultureInfo); + return dateTime; + } + catch (Exception) + { + return DateTime.MinValue; } + } - public void PushValue(LogExpert.ILogLineColumnizerCallback callback, int column, string value, string oldValue) + public void PushValue (ILogLineColumnizerCallback callback, int column, string value, string oldValue) + { + if (column == 1) { - if (column == 1) + try { - try - { - FormatInfo formatInfo = _timeFormatDeterminer.DetermineTimeFormatInfo(oldValue); - if (formatInfo == null) - { - return; - } - DateTime newDateTime = DateTime.ParseExact(value, formatInfo.TimeFormat, formatInfo.CultureInfo); - DateTime oldDateTime = DateTime.ParseExact(oldValue, formatInfo.TimeFormat, formatInfo.CultureInfo); - long mSecsOld = oldDateTime.Ticks / TimeSpan.TicksPerMillisecond; - long mSecsNew = newDateTime.Ticks / TimeSpan.TicksPerMillisecond; - timeOffset = (int)(mSecsNew - mSecsOld); - } - catch (FormatException) + FormatInfo formatInfo = _timeFormatDeterminer.DetermineTimeFormatInfo(oldValue); + if (formatInfo == null) { + return; } + var newDateTime = DateTime.ParseExact(value, formatInfo.TimeFormat, formatInfo.CultureInfo); + var oldDateTime = DateTime.ParseExact(oldValue, formatInfo.TimeFormat, formatInfo.CultureInfo); + var mSecsOld = oldDateTime.Ticks / TimeSpan.TicksPerMillisecond; + var mSecsNew = newDateTime.Ticks / TimeSpan.TicksPerMillisecond; + timeOffset = (int)(mSecsNew - mSecsOld); + } + catch (FormatException) + { } } + } - public string GetName() - { - return "Timestamp Columnizer"; - } + public string GetName () + { + return "Timestamp Columnizer"; + } - public string GetDescription() - { - return "Splits every line into 3 fields: Date, Time and the rest of the log message"; - } + public string GetDescription () + { + return "Splits every line into 3 fields: Date, Time and the rest of the log message"; + } - public int GetColumnCount() - { - return 3; - } + public int GetColumnCount () + { + return 3; + } - public string[] GetColumnNames() - { - return new string[] { "Date", "Time", "Message" }; - } + public string[] GetColumnNames () + { + return ["Date", "Time", "Message"]; + } - public IColumnizedLogLine SplitLine(LogExpert.ILogLineColumnizerCallback callback, ILogLine line) - { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - // 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 - // 03.01.2008 14:48:00.066 + public IColumnizedLogLine SplitLine (ILogLineColumnizerCallback callback, ILogLine line) + { + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + // 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 + // 03.01.2008 14:48:00.066 - ColumnizedLogLine clogLine = new(); - clogLine.LogLine = line; + ColumnizedLogLine clogLine = new(); + clogLine.LogLine = line; - Column[] columns = new Column[3] - { - new() {FullValue = "", Parent = clogLine}, - new() {FullValue = "", Parent = clogLine}, - new() {FullValue = "", Parent = clogLine}, - }; + var columns = new Column[3] + { + new() {FullValue = "", Parent = clogLine}, + new() {FullValue = "", Parent = clogLine}, + new() {FullValue = "", Parent = clogLine}, + }; - clogLine.ColumnValues = columns.Select(a => a as IColumn).ToArray(); + clogLine.ColumnValues = columns.Select(a => a as IColumn).ToArray(); - string temp = line.FullLine; + var temp = line.FullLine; - FormatInfo formatInfo = _timeFormatDeterminer.DetermineDateTimeFormatInfo(temp); - if (formatInfo == null) - { - columns[2].FullValue = temp; - return clogLine; - } - int endPos = formatInfo.DateTimeFormat.Length; - int timeLen = formatInfo.TimeFormat.Length; - int dateLen = formatInfo.DateFormat.Length; - try + FormatInfo formatInfo = _timeFormatDeterminer.DetermineDateTimeFormatInfo(temp); + if (formatInfo == null) + { + columns[2].FullValue = temp; + return clogLine; + } + var endPos = formatInfo.DateTimeFormat.Length; + var timeLen = formatInfo.TimeFormat.Length; + var dateLen = formatInfo.DateFormat.Length; + try + { + if (timeOffset != 0) { - if (timeOffset != 0) + if (formatInfo.IgnoreFirstChar) { - if (formatInfo.IgnoreFirstChar) - { - // First character is a bracket and should be ignored - DateTime dateTime = DateTime.ParseExact(temp.Substring(1, endPos), formatInfo.DateTimeFormat, - formatInfo.CultureInfo); - dateTime = dateTime.Add(new TimeSpan(0, 0, 0, 0, timeOffset)); - string newDate = dateTime.ToString(formatInfo.DateTimeFormat, formatInfo.CultureInfo); - columns[0].FullValue = newDate.Substring(0, dateLen); // date - columns[1].FullValue = newDate.Substring(dateLen + 1, timeLen); // time - columns[2].FullValue = temp.Substring(endPos + 2); // rest of line - } - else - { - DateTime dateTime = DateTime.ParseExact(temp.Substring(0, endPos), formatInfo.DateTimeFormat, - formatInfo.CultureInfo); - dateTime = dateTime.Add(new TimeSpan(0, 0, 0, 0, timeOffset)); - string newDate = dateTime.ToString(formatInfo.DateTimeFormat, formatInfo.CultureInfo); - columns[0].FullValue = newDate.Substring(0, dateLen); // date - columns[1].FullValue = newDate.Substring(dateLen + 1, timeLen); // time - columns[2].FullValue = temp.Substring(endPos); // rest of line - } + // First character is a bracket and should be ignored + var dateTime = DateTime.ParseExact(temp.Substring(1, endPos), formatInfo.DateTimeFormat, + formatInfo.CultureInfo); + dateTime = dateTime.Add(new TimeSpan(0, 0, 0, 0, timeOffset)); + var newDate = dateTime.ToString(formatInfo.DateTimeFormat, formatInfo.CultureInfo); + columns[0].FullValue = newDate.Substring(0, dateLen); // date + columns[1].FullValue = newDate.Substring(dateLen + 1, timeLen); // time + columns[2].FullValue = temp.Substring(endPos + 2); // rest of line } else { - if (formatInfo.IgnoreFirstChar) - { - // First character is a bracket and should be ignored - columns[0].FullValue = temp.Substring(1, dateLen); // date - columns[1].FullValue = temp.Substring(dateLen + 2, timeLen); // time - columns[2].FullValue = temp.Substring(endPos + 2); // rest of line - } - else - { - columns[0].FullValue = temp.Substring(0, dateLen); // date - columns[1].FullValue = temp.Substring(dateLen + 1, timeLen); // time - columns[2].FullValue = temp.Substring(endPos); // rest of line - } + var dateTime = DateTime.ParseExact(temp.Substring(0, endPos), formatInfo.DateTimeFormat, + formatInfo.CultureInfo); + dateTime = dateTime.Add(new TimeSpan(0, 0, 0, 0, timeOffset)); + var newDate = dateTime.ToString(formatInfo.DateTimeFormat, formatInfo.CultureInfo); + columns[0].FullValue = newDate.Substring(0, dateLen); // date + columns[1].FullValue = newDate.Substring(dateLen + 1, timeLen); // time + columns[2].FullValue = temp.Substring(endPos); // rest of line } } - catch (Exception) + else { - columns[0].FullValue = "n/a"; - columns[1].FullValue = "n/a"; - columns[2].FullValue = temp; - } - return clogLine; - } - - public Priority GetPriority(string fileName, IEnumerable samples) - { - Priority result = Priority.NotSupport; - - int timeStampCount = 0; - foreach (var line in samples) - { - if (line == null || string.IsNullOrEmpty(line.FullLine)) + if (formatInfo.IgnoreFirstChar) { - continue; - } - var timeDeterminer = new TimeFormatDeterminer(); - if (null != timeDeterminer.DetermineDateTimeFormatInfo(line.FullLine)) - { - timeStampCount++; + // First character is a bracket and should be ignored + columns[0].FullValue = temp.Substring(1, dateLen); // date + columns[1].FullValue = temp.Substring(dateLen + 2, timeLen); // time + columns[2].FullValue = temp.Substring(endPos + 2); // rest of line } else { - timeStampCount--; + columns[0].FullValue = temp.Substring(0, dateLen); // date + columns[1].FullValue = temp.Substring(dateLen + 1, timeLen); // time + columns[2].FullValue = temp.Substring(endPos); // rest of line } } + } + catch (Exception) + { + columns[0].FullValue = "n/a"; + columns[1].FullValue = "n/a"; + columns[2].FullValue = temp; + } + return clogLine; + } - if (timeStampCount > 0) + public Priority GetPriority (string fileName, IEnumerable samples) + { + Priority result = Priority.NotSupport; + + var timeStampCount = 0; + foreach (ILogLine line in samples) + { + if (line == null || string.IsNullOrEmpty(line.FullLine)) + { + continue; + } + var timeDeterminer = new TimeFormatDeterminer(); + if (null != timeDeterminer.DetermineDateTimeFormatInfo(line.FullLine)) { - result = Priority.WellSupport; + timeStampCount++; } + else + { + timeStampCount--; + } + } - return result; + if (timeStampCount > 0) + { + result = Priority.WellSupport; } - #endregion + return result; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/DateTimeParser/DateFormatPartAdjuster.cs b/src/LogExpert.Core/Classes/DateTimeParser/DateFormatPartAdjuster.cs index 0855f9e5..b0277ee5 100644 --- a/src/LogExpert.Core/Classes/DateTimeParser/DateFormatPartAdjuster.cs +++ b/src/LogExpert.Core/Classes/DateTimeParser/DateFormatPartAdjuster.cs @@ -1,36 +1,35 @@ using System; using System.Collections.Generic; -namespace LogExpert.Core.Classes.DateTimeParser +namespace LogExpert.Core.Classes.DateTimeParser; + +// Ensures we have constant width (number of characters) date formats +public static class DateFormatPartAdjuster { - // Ensures we have constant width (number of characters) date formats - public static class DateFormatPartAdjuster + private static readonly IDictionary _dateTimePartReplacements = new Dictionary(StringComparer.OrdinalIgnoreCase) { - private static readonly IDictionary _dateTimePartReplacements = new Dictionary(StringComparer.OrdinalIgnoreCase) - { - ["y"] = "yyy", - ["yyy"] = "yyyy", - ["m"] = "mm", - ["d"] = "dd", - ["h"] = "hh", - ["s"] = "ss" - }; + ["y"] = "yyy", + ["yyy"] = "yyyy", + ["m"] = "mm", + ["d"] = "dd", + ["h"] = "hh", + ["s"] = "ss" + }; - public static string AdjustDateTimeFormatPart(string part) + public static string AdjustDateTimeFormatPart(string part) + { + if (!_dateTimePartReplacements.TryGetValue(part, out var adjustedPart)) { - if (!_dateTimePartReplacements.TryGetValue(part, out string adjustedPart)) - { - return part; - } + return part; + } - if (char.IsUpper(part[0])) - { - return adjustedPart.ToUpper(); - } - else - { - return adjustedPart.ToLower(); - } + if (char.IsUpper(part[0])) + { + return adjustedPart.ToUpper(); + } + else + { + return adjustedPart.ToLower(); } } } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/DateTimeParser/Parser.cs b/src/LogExpert.Core/Classes/DateTimeParser/Parser.cs index cb558c06..a6528267 100644 --- a/src/LogExpert.Core/Classes/DateTimeParser/Parser.cs +++ b/src/LogExpert.Core/Classes/DateTimeParser/Parser.cs @@ -1,172 +1,170 @@ -namespace LogExpert.Core.Classes.DateTimeParser +namespace LogExpert.Core.Classes.DateTimeParser; + +public static class Parser { - public static class Parser + public static List
ParseSections(string formatString, out bool syntaxError) { - public static List
ParseSections(string formatString, out bool syntaxError) + var tokenizer = new Tokenizer(formatString); + var sections = new List
(); + syntaxError = false; + while (true) { - var tokenizer = new Tokenizer(formatString); - var sections = new List
(); - syntaxError = false; - while (true) - { - var section = ParseSection(tokenizer, sections.Count, out var sectionSyntaxError); - - if (sectionSyntaxError) - { - syntaxError = true; - } + var section = ParseSection(tokenizer, sections.Count, out var sectionSyntaxError); - if (section == null) - { - break; - } + if (sectionSyntaxError) + { + syntaxError = true; + } - sections.Add(section); + if (section == null) + { + break; } - return sections; + sections.Add(section); } - private static Section ParseSection(Tokenizer reader, int index, out bool syntaxError) - { - bool hasDateParts = false; - string token; - List tokens = []; - - while ((token = ReadToken(reader, out syntaxError)) != null) - { - if (token == ";") - { - break; - } + return sections; + } - if (Token.IsDatePart(token)) - { - hasDateParts |= true; - tokens.Add(token); - } - else - { - tokens.Add(token); - } - } + private static Section ParseSection(Tokenizer reader, int index, out bool syntaxError) + { + var hasDateParts = false; + string token; + List tokens = []; - if (syntaxError || tokens.Count == 0) + while ((token = ReadToken(reader, out syntaxError)) != null) + { + if (token == ";") { - return null; + break; } - List generalTextDateDuration = null; - - if (hasDateParts) + if (Token.IsDatePart(token)) { - ParseMilliseconds(tokens, out generalTextDateDuration); + hasDateParts |= true; + tokens.Add(token); } else { - // Unable to parse format string - syntaxError = true; - return null; + tokens.Add(token); } + } - return new Section() - { - SectionIndex = index, - GeneralTextDateDurationParts = generalTextDateDuration - }; + if (syntaxError || tokens.Count == 0) + { + return null; } - private static void ParseMilliseconds(List tokens, out List result) + List generalTextDateDuration; + if (hasDateParts) { - // if tokens form .0 through .000.., combine to single subsecond token - result = []; - for (var i = 0; i < tokens.Count; i++) + ParseMilliseconds(tokens, out generalTextDateDuration); + } + else + { + // Unable to parse format string + syntaxError = true; + return null; + } + + return new Section() + { + SectionIndex = index, + GeneralTextDateDurationParts = generalTextDateDuration + }; + } + + private static void ParseMilliseconds(List tokens, out List result) + { + // if tokens form .0 through .000.., combine to single subsecond token + result = []; + for (var i = 0; i < tokens.Count; i++) + { + var token = tokens[i]; + if (token == ".") { - var token = tokens[i]; - if (token == ".") + var zeros = 0; + while (i + 1 < tokens.Count && tokens[i + 1] == "0") + { + i++; + zeros++; + } + + if (zeros > 0) { - var zeros = 0; - while (i + 1 < tokens.Count && tokens[i + 1] == "0") - { - i++; - zeros++; - } - - if (zeros > 0) - { - result.Add("." + new string('0', zeros)); - } - else - { - result.Add("."); - } + result.Add("." + new string('0', zeros)); } else { - result.Add(token); + result.Add("."); } } - } - - private static string ReadToken(Tokenizer reader, out bool syntaxError) - { - var offset = reader.Position; - if (ReadLiteral(reader)) + else { - syntaxError = false; - var length = reader.Position - offset; - return reader.Substring(offset, length); + result.Add(token); } + } + } - if ( - // Symbols - reader.ReadOneOf("#?,!&%+-$€£0123456789{}():;/.@ ") || - - // Date - reader.ReadString("tt", true) || //AM / PM - reader.ReadOneOrMore('y') || - reader.ReadOneOrMore('Y') || - reader.ReadOneOrMore('m') || - reader.ReadOneOrMore('M') || - reader.ReadOneOrMore('d') || - reader.ReadOneOrMore('D') || - reader.ReadOneOrMore('h') || - reader.ReadOneOrMore('H') || - reader.ReadOneOrMore('s') || - reader.ReadOneOrMore('S') || - //Latin Date String: (a.C.n. ante Christum natum) - reader.ReadString("gg")) - { - syntaxError = false; - var length = reader.Position - offset; - return reader.Substring(offset, length); - } + private static string ReadToken(Tokenizer reader, out bool syntaxError) + { + var offset = reader.Position; + if (ReadLiteral(reader)) + { + syntaxError = false; + var length = reader.Position - offset; + return reader.Substring(offset, length); + } + if ( // Symbols - - syntaxError = reader.Position < reader.Length; - return null; + reader.ReadOneOf("#?,!&%+-$€£0123456789{}():;/.@ ") || + + // Date + reader.ReadString("tt", true) || //AM / PM + reader.ReadOneOrMore('y') || + reader.ReadOneOrMore('Y') || + reader.ReadOneOrMore('m') || + reader.ReadOneOrMore('M') || + reader.ReadOneOrMore('d') || + reader.ReadOneOrMore('D') || + reader.ReadOneOrMore('h') || + reader.ReadOneOrMore('H') || + reader.ReadOneOrMore('s') || + reader.ReadOneOrMore('S') || + //Latin Date String: (a.C.n. ante Christum natum) + reader.ReadString("gg")) + { + syntaxError = false; + var length = reader.Position - offset; + return reader.Substring(offset, length); } - private static bool ReadLiteral(Tokenizer reader) - { - if (reader.Peek() == '\\' || reader.Peek() == '*' || reader.Peek() == '_') - { - reader.Advance(2); - return true; - } + // Symbols - if (reader.ReadEnclosed('"', '"')) - { - return true; - } + syntaxError = reader.Position < reader.Length; + return null; + } - if (reader.ReadEnclosed('\'', '\'')) - { - return true; - } + private static bool ReadLiteral(Tokenizer reader) + { + if (reader.Peek() == '\\' || reader.Peek() == '*' || reader.Peek() == '_') + { + reader.Advance(2); + return true; + } - return false; + if (reader.ReadEnclosed('"', '"')) + { + return true; } + + if (reader.ReadEnclosed('\'', '\'')) + { + return true; + } + + return false; } } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/DateTimeParser/Section.cs b/src/LogExpert.Core/Classes/DateTimeParser/Section.cs index 5f492b0e..a6d14c82 100644 --- a/src/LogExpert.Core/Classes/DateTimeParser/Section.cs +++ b/src/LogExpert.Core/Classes/DateTimeParser/Section.cs @@ -1,11 +1,10 @@ using System.Collections.Generic; -namespace LogExpert.Core.Classes.DateTimeParser +namespace LogExpert.Core.Classes.DateTimeParser; + +public class Section { - public class Section - { - public int SectionIndex { get; set; } + public int SectionIndex { get; set; } - public List GeneralTextDateDurationParts { get; set; } - } + public List GeneralTextDateDurationParts { get; set; } } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/DateTimeParser/Token.cs b/src/LogExpert.Core/Classes/DateTimeParser/Token.cs index 07483b9a..a9869b55 100644 --- a/src/LogExpert.Core/Classes/DateTimeParser/Token.cs +++ b/src/LogExpert.Core/Classes/DateTimeParser/Token.cs @@ -1,18 +1,17 @@ using System; -namespace LogExpert.Core.Classes.DateTimeParser +namespace LogExpert.Core.Classes.DateTimeParser; + +public static class Token { - public static class Token + public static bool IsDatePart(string token) { - public static bool IsDatePart(string token) - { - return - token.StartsWith("y", StringComparison.OrdinalIgnoreCase) || - token.StartsWith("m", StringComparison.OrdinalIgnoreCase) || - token.StartsWith("d", StringComparison.OrdinalIgnoreCase) || - token.StartsWith("s", StringComparison.OrdinalIgnoreCase) || - token.StartsWith("h", StringComparison.OrdinalIgnoreCase) || - string.Compare(token, "tt", StringComparison.OrdinalIgnoreCase) == 0; - } + return + token.StartsWith("y", StringComparison.OrdinalIgnoreCase) || + token.StartsWith("m", StringComparison.OrdinalIgnoreCase) || + token.StartsWith("d", StringComparison.OrdinalIgnoreCase) || + token.StartsWith("s", StringComparison.OrdinalIgnoreCase) || + token.StartsWith("h", StringComparison.OrdinalIgnoreCase) || + string.Compare(token, "tt", StringComparison.OrdinalIgnoreCase) == 0; } } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/DateTimeParser/Tokenizer.cs b/src/LogExpert.Core/Classes/DateTimeParser/Tokenizer.cs index baf16dba..ae68743c 100644 --- a/src/LogExpert.Core/Classes/DateTimeParser/Tokenizer.cs +++ b/src/LogExpert.Core/Classes/DateTimeParser/Tokenizer.cs @@ -1,141 +1,140 @@ using System; -namespace LogExpert.Core.Classes.DateTimeParser +namespace LogExpert.Core.Classes.DateTimeParser; + +internal class Tokenizer { - internal class Tokenizer + private string formatString; + private int formatStringPosition; + + public Tokenizer(string fmt) { - private string formatString; - private int formatStringPosition = 0; + formatString = fmt; + } - public Tokenizer(string fmt) - { - formatString = fmt; - } + public int Position => formatStringPosition; - public int Position => formatStringPosition; + public int Length => formatString.Length; - public int Length => formatString.Length; + public string Substring(int startIndex, int length) + { + return formatString.Substring(startIndex, length); + } - public string Substring(int startIndex, int length) + public int Peek(int offset = 0) + { + if (formatStringPosition + offset >= formatString.Length) { - return formatString.Substring(startIndex, length); + return -1; } - public int Peek(int offset = 0) + return formatString[formatStringPosition + offset]; + } + + public int PeekUntil(int startOffset, int until) + { + var offset = startOffset; + while (true) { - if (formatStringPosition + offset >= formatString.Length) + var c = Peek(offset++); + if (c == -1) { - return -1; + break; } - return formatString[formatStringPosition + offset]; - } - - public int PeekUntil(int startOffset, int until) - { - int offset = startOffset; - while (true) + if (c == until) { - var c = Peek(offset++); - if (c == -1) - { - break; - } - - if (c == until) - { - return offset - startOffset; - } + return offset - startOffset; } - return 0; } + return 0; + } - public bool PeekOneOf(int offset, string s) + public bool PeekOneOf(int offset, string s) + { + foreach (var c in s) { - foreach (var c in s) + if (Peek(offset) == c) { - if (Peek(offset) == c) - { - return true; - } + return true; } - return false; } + return false; + } - public void Advance(int characters = 1) + public void Advance(int characters = 1) + { + formatStringPosition = Math.Min(formatStringPosition + characters, formatString.Length); + } + + public bool ReadOneOrMore(int c) + { + if (Peek() != c) { - formatStringPosition = Math.Min(formatStringPosition + characters, formatString.Length); + return false; } - public bool ReadOneOrMore(int c) + while (Peek() == c) { - if (Peek() != c) - { - return false; - } + Advance(); + } - while (Peek() == c) - { - Advance(); - } + return true; + } + public bool ReadOneOf(string s) + { + if (PeekOneOf(0, s)) + { + Advance(); return true; } + return false; + } - public bool ReadOneOf(string s) + public bool ReadString(string s, bool ignoreCase = false) + { + if (formatStringPosition + s.Length > formatString.Length) { - if (PeekOneOf(0, s)) - { - Advance(); - return true; - } return false; } - public bool ReadString(string s, bool ignoreCase = false) + for (var i = 0; i < s.Length; i++) { - if (formatStringPosition + s.Length > formatString.Length) - { - return false; - } - - for (var i = 0; i < s.Length; i++) + var c1 = s[i]; + var c2 = (char)Peek(i); + if (ignoreCase) { - var c1 = s[i]; - var c2 = (char)Peek(i); - if (ignoreCase) + if (char.ToLower(c1) != char.ToLower(c2)) { - if (char.ToLower(c1) != char.ToLower(c2)) - { - return false; - } + return false; } - else + } + else + { + if (c1 != c2) { - if (c1 != c2) - { - return false; - } + return false; } } - - Advance(s.Length); - return true; } - public bool ReadEnclosed(char open, char close) + Advance(s.Length); + return true; + } + + public bool ReadEnclosed(char open, char close) + { + if (Peek() == open) { - if (Peek() == open) + var length = PeekUntil(1, close); + if (length > 0) { - int length = PeekUntil(1, close); - if (length > 0) - { - Advance(1 + length); - return true; - } + Advance(1 + length); + return true; } - - return false; } + + return false; } } diff --git a/src/LogExpert.Core/Classes/FileSystemCallback.cs b/src/LogExpert.Core/Classes/FileSystemCallback.cs index 0fe50759..008f2b29 100644 --- a/src/LogExpert.Core/Classes/FileSystemCallback.cs +++ b/src/LogExpert.Core/Classes/FileSystemCallback.cs @@ -1,49 +1,48 @@ using NLog; -namespace LogExpert.Core.Classes -{ - public class FileSystemCallback : IFileSystemCallback - { - #region Public methods +namespace LogExpert.Core.Classes; - public ILogExpertLogger GetLogger() - { - return new NLogLogExpertWrapper(); - } +public class FileSystemCallback : IFileSystemCallback +{ + #region Public methods - #endregion + public ILogExpertLogger GetLogger() + { + return new NLogLogExpertWrapper(); + } - private class NLogLogExpertWrapper : ILogExpertLogger - { - #region Fields + #endregion - private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); + private class NLogLogExpertWrapper : ILogExpertLogger + { + #region Fields - #endregion + private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); - #region Public methods + #endregion - public void Info(string msg) - { - _logger.Info(msg); - } + #region Public methods - public void Debug(string msg) - { - _logger.Debug(msg); - } + public void Info(string msg) + { + _logger.Info(msg); + } - public void LogWarn(string msg) - { - _logger.Warn(msg); - } + public void Debug(string msg) + { + _logger.Debug(msg); + } - public void LogError(string msg) - { - _logger.Error(msg); - } + public void LogWarn(string msg) + { + _logger.Warn(msg); + } - #endregion + public void LogError(string msg) + { + _logger.Error(msg); } + + #endregion } } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Filter/Filter.cs b/src/LogExpert.Core/Classes/Filter/Filter.cs index f7ee2603..d1374c79 100644 --- a/src/LogExpert.Core/Classes/Filter/Filter.cs +++ b/src/LogExpert.Core/Classes/Filter/Filter.cs @@ -3,176 +3,175 @@ using LogExpert.Core.Classes.Filter; using NLog; -namespace LogExpert.Classes.Filter +namespace LogExpert.Classes.Filter; + +internal delegate void FilterFx (FilterParams filterParams, List filterResultLines, List lastFilterResultLines, List filterHitList); + +internal class Filter { - internal delegate void FilterFx (FilterParams filterParams, List filterResultLines, List lastFilterResultLines, List filterHitList); + #region Fields - internal class Filter - { - #region Fields + private const int PROGRESS_BAR_MODULO = 1000; + private const int SPREAD_MAX = 50; + private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); - private const int PROGRESS_BAR_MODULO = 1000; - private const int SPREAD_MAX = 50; - private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); + private readonly ColumnizerCallback _callback; - private readonly ColumnizerCallback _callback; + #endregion - #endregion + #region cTor - #region cTor + //TODO Is the callback needed? (https://github.com/LogExperts/LogExpert/issues/401) + public Filter (ColumnizerCallback callback) + { + _callback = callback; + FilterResultLines = []; + LastFilterLinesList = []; + FilterHitList = []; + } - //TODO Is the callback needed? (https://github.com/LogExperts/LogExpert/issues/401) - public Filter (ColumnizerCallback callback) - { - _callback = callback; - FilterResultLines = []; - LastFilterLinesList = []; - FilterHitList = []; - } + #endregion - #endregion + #region Properties - #region Properties + public List FilterResultLines { get; } - public List FilterResultLines { get; } + public List LastFilterLinesList { get; } - public List LastFilterLinesList { get; } + public List FilterHitList { get; } - public List FilterHitList { get; } + public bool ShouldCancel { get; set; } - public bool ShouldCancel { get; set; } = false; + #endregion - #endregion + #region Public methods - #region Public methods + public int DoFilter (FilterParams filterParams, int startLine, int maxCount, ProgressCallback progressCallback) + { + return DoFilter(filterParams, startLine, maxCount, FilterResultLines, LastFilterLinesList, FilterHitList, progressCallback); + } - public int DoFilter (FilterParams filterParams, int startLine, int maxCount, ProgressCallback progressCallback) - { - return DoFilter(filterParams, startLine, maxCount, FilterResultLines, LastFilterLinesList, FilterHitList, progressCallback); - } + #endregion - #endregion + #region Private Methods - #region Private Methods + private int DoFilter (FilterParams filterParams, int startLine, int maxCount, List filterResultLines, List lastFilterLinesList, List filterHitList, ProgressCallback progressCallback) + { + var lineNum = startLine; + var count = 0; + var callbackCounter = 0; - private int DoFilter (FilterParams filterParams, int startLine, int maxCount, List filterResultLines, List lastFilterLinesList, List filterHitList, ProgressCallback progressCallback) + try { - var lineNum = startLine; - var count = 0; - var callbackCounter = 0; + filterParams.Reset(); - try + while ((count++ < maxCount || filterParams.IsInRange) && !ShouldCancel) { - filterParams.Reset(); - - while ((count++ < maxCount || filterParams.IsInRange) && !ShouldCancel) + if (lineNum >= _callback.GetLineCount()) { - if (lineNum >= _callback.GetLineCount()) - { - return count; - } + return count; + } - ILogLine line = _callback.GetLogLine(lineNum); + ILogLine line = _callback.GetLogLine(lineNum); - if (line == null) - { - return count; - } + if (line == null) + { + return count; + } - _callback.SetLineNum(lineNum); + _callback.SetLineNum(lineNum); - if (Util.TestFilterCondition(filterParams, line, _callback)) - { - AddFilterLine(lineNum, false, filterParams, filterResultLines, lastFilterLinesList, filterHitList); - } + if (Util.TestFilterCondition(filterParams, line, _callback)) + { + AddFilterLine(lineNum, false, filterParams, filterResultLines, lastFilterLinesList, filterHitList); + } - lineNum++; - callbackCounter++; + lineNum++; + callbackCounter++; - if (lineNum % PROGRESS_BAR_MODULO == 0) - { - progressCallback(callbackCounter); - callbackCounter = 0; - } + if (lineNum % PROGRESS_BAR_MODULO == 0) + { + progressCallback(callbackCounter); + callbackCounter = 0; } } - catch (Exception ex) - { - _logger.Error(ex, "Exception while filtering. Please report to developer"); - //TODO: This information should be handled from the LogExpert project and not from LogExpert.Core. - //MessageBox.Show(null, - // "Exception while filtering. Please report to developer: \n\n" + ex + "\n\n" + ex.StackTrace, - // "LogExpert"); - } - - return count; } - - private void AddFilterLine (int lineNum, bool immediate, FilterParams filterParams, List filterResultLines, List lastFilterLinesList, List filterHitList) + catch (Exception ex) { - filterHitList.Add(lineNum); - IList filterResult = GetAdditionalFilterResults(filterParams, lineNum, lastFilterLinesList); + _logger.Error(ex, "Exception while filtering. Please report to developer"); + //TODO: This information should be handled from the LogExpert project and not from LogExpert.Core. + //MessageBox.Show(null, + // "Exception while filtering. Please report to developer: \n\n" + ex + "\n\n" + ex.StackTrace, + // "LogExpert"); + } - filterResultLines.AddRange(filterResult); + return count; + } - lastFilterLinesList.AddRange(filterResult); + private void AddFilterLine (int lineNum, bool immediate, FilterParams filterParams, List filterResultLines, List lastFilterLinesList, List filterHitList) + { + filterHitList.Add(lineNum); + IList filterResult = GetAdditionalFilterResults(filterParams, lineNum, lastFilterLinesList); - if (lastFilterLinesList.Count > SPREAD_MAX * 2) - { - lastFilterLinesList.RemoveRange(0, lastFilterLinesList.Count - SPREAD_MAX * 2); - } - } + filterResultLines.AddRange(filterResult); + lastFilterLinesList.AddRange(filterResult); - /// - /// Returns a list with 'additional filter results'. This is the given line number - /// and (if back spread and/or fore spread is enabled) some additional lines. - /// This function doesn't check the filter condition! - /// - /// - /// - /// - /// - private IList GetAdditionalFilterResults (FilterParams filterParams, int lineNum, IList checkList) + if (lastFilterLinesList.Count > SPREAD_MAX * 2) { - IList resultList = []; + lastFilterLinesList.RemoveRange(0, lastFilterLinesList.Count - SPREAD_MAX * 2); + } + } - if (filterParams.SpreadBefore == 0 && filterParams.SpreadBehind == 0) - { - resultList.Add(lineNum); - return resultList; - } - // back spread - for (int i = filterParams.SpreadBefore; i > 0; --i) + /// + /// Returns a list with 'additional filter results'. This is the given line number + /// and (if back spread and/or fore spread is enabled) some additional lines. + /// This function doesn't check the filter condition! + /// + /// + /// + /// + /// + private IList GetAdditionalFilterResults (FilterParams filterParams, int lineNum, IList checkList) + { + IList resultList = []; + + if (filterParams.SpreadBefore == 0 && filterParams.SpreadBehind == 0) + { + resultList.Add(lineNum); + return resultList; + } + + // back spread + for (var i = filterParams.SpreadBefore; i > 0; --i) + { + if (lineNum - i > 0) { - if (lineNum - i > 0) + if (!resultList.Contains(lineNum - i) && !checkList.Contains(lineNum - i)) { - if (!resultList.Contains(lineNum - i) && !checkList.Contains(lineNum - i)) - { - resultList.Add(lineNum - i); - } + resultList.Add(lineNum - i); } } - // direct filter hit - if (!resultList.Contains(lineNum) && !checkList.Contains(lineNum)) - { - resultList.Add(lineNum); - } - // after spread - for (int i = 1; i <= filterParams.SpreadBehind; ++i) + } + // direct filter hit + if (!resultList.Contains(lineNum) && !checkList.Contains(lineNum)) + { + resultList.Add(lineNum); + } + // after spread + for (var i = 1; i <= filterParams.SpreadBehind; ++i) + { + if (lineNum + i < _callback.GetLineCount()) { - if (lineNum + i < _callback.GetLineCount()) + if (!resultList.Contains(lineNum + i) && !checkList.Contains(lineNum + i)) { - if (!resultList.Contains(lineNum + i) && !checkList.Contains(lineNum + i)) - { - resultList.Add(lineNum + i); - } + resultList.Add(lineNum + i); } } - return resultList; } - - #endregion + return resultList; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Filter/FilterCancelHandler.cs b/src/LogExpert.Core/Classes/Filter/FilterCancelHandler.cs index 6a4c8c6b..18b7dd50 100644 --- a/src/LogExpert.Core/Classes/Filter/FilterCancelHandler.cs +++ b/src/LogExpert.Core/Classes/Filter/FilterCancelHandler.cs @@ -2,34 +2,33 @@ using NLog; -namespace LogExpert.Classes.Filter -{ - public class FilterCancelHandler : IBackgroundProcessCancelHandler - { - private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); - #region Fields +namespace LogExpert.Classes.Filter; - private readonly FilterStarter _filterStarter; +public class FilterCancelHandler : IBackgroundProcessCancelHandler +{ + private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); + #region Fields - #endregion + private readonly FilterStarter _filterStarter; - #region cTor + #endregion - public FilterCancelHandler(FilterStarter filterStarter) - { - _filterStarter = filterStarter; - } + #region cTor - #endregion + public FilterCancelHandler(FilterStarter filterStarter) + { + _filterStarter = filterStarter; + } - #region Public methods + #endregion - public void EscapePressed() - { - _logger.Info("FilterCancelHandler called."); - _filterStarter.CancelFilter(); - } + #region Public methods - #endregion + public void EscapePressed() + { + _logger.Info("FilterCancelHandler called."); + _filterStarter.CancelFilter(); } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Filter/FilterParams.cs b/src/LogExpert.Core/Classes/Filter/FilterParams.cs index d59c9deb..57ff7ec2 100644 --- a/src/LogExpert.Core/Classes/Filter/FilterParams.cs +++ b/src/LogExpert.Core/Classes/Filter/FilterParams.cs @@ -3,170 +3,169 @@ using System.Text.Json.Serialization; using System.Text.RegularExpressions; -namespace LogExpert.Core.Classes.Filter +namespace LogExpert.Core.Classes.Filter; + +[Serializable] +public class FilterParams : ICloneable { - [Serializable] - public class FilterParams : ICloneable - { - #region Fields + #region Fields - private string _rangeSearchText = string.Empty; - private string _searchText = string.Empty; + private string _rangeSearchText = string.Empty; + private string _searchText = string.Empty; - //public List historyList = new List(); - //public List rangeHistoryList = new List(); + //public List historyList = new List(); + //public List rangeHistoryList = new List(); - #endregion + #endregion - #region Properties + #region Properties - public string SearchText + public string SearchText + { + get => _searchText; + set { - get => _searchText; - set - { - _searchText = value; - LowerSearchText = _searchText.ToLowerInvariant(); - } + _searchText = value; + LowerSearchText = _searchText.ToLowerInvariant(); } + } - public string RangeSearchText + public string RangeSearchText + { + get => _rangeSearchText; + set { - get => _rangeSearchText; - set - { - _rangeSearchText = value; - LowerRangeSearchText = _rangeSearchText.ToLowerInvariant(); - } + _rangeSearchText = value; + LowerRangeSearchText = _rangeSearchText.ToLowerInvariant(); } + } - public bool SpreadEnabled => SpreadBefore > 0 || SpreadBehind > 0; + public bool SpreadEnabled => SpreadBefore > 0 || SpreadBehind > 0; - public bool IsCaseSensitive { get; set; } + public bool IsCaseSensitive { get; set; } - public bool IsFilterTail { get; set; } + public bool IsFilterTail { get; set; } - public int FuzzyValue { get; set; } + public int FuzzyValue { get; set; } - public bool EmptyColumnUsePrev { get; set; } + public bool EmptyColumnUsePrev { get; set; } - public bool EmptyColumnHit { get; set; } + public bool EmptyColumnHit { get; set; } - public bool ExactColumnMatch { get; set; } = false; + public bool ExactColumnMatch { get; set; } - public bool ColumnRestrict { get; set; } + public bool ColumnRestrict { get; set; } - public Color Color { get; set; } = Color.Black; + public Color Color { get; set; } = Color.Black; - public int SpreadBefore { get; set; } + public int SpreadBefore { get; set; } - public int SpreadBehind { get; set; } + public int SpreadBehind { get; set; } - public bool IsInvert { get; set; } + public bool IsInvert { get; set; } - public bool IsRangeSearch { get; set; } = false; + public bool IsRangeSearch { get; set; } - public bool IsRegex { get; set; } + public bool IsRegex { get; set; } - // list of columns in which to search - public List ColumnList { get; set; } = []; + // list of columns in which to search + public List ColumnList { get; set; } = []; - [JsonIgnore] - [field: NonSerialized] - public ILogLineColumnizer CurrentColumnizer { get; set; } + [JsonIgnore] + [field: NonSerialized] + public ILogLineColumnizer CurrentColumnizer { get; set; } - /// - /// false=looking for start - /// true=looking for end - /// - [field: NonSerialized] - public bool IsInRange { get; set; } = false; + /// + /// false=looking for start + /// true=looking for end + /// + [field: NonSerialized] + public bool IsInRange { get; set; } - [field: NonSerialized] - public string LastLine { get; set; } = string.Empty; + [field: NonSerialized] + public string LastLine { get; set; } = string.Empty; - [field: NonSerialized] - public Hashtable LastNonEmptyCols { get; set; } = []; + [field: NonSerialized] + public Hashtable LastNonEmptyCols { get; set; } = []; - [field: NonSerialized] - public bool LastResult { get; set; } + [field: NonSerialized] + public bool LastResult { get; set; } - [field: NonSerialized] - public string LowerRangeSearchText { get; set; } = string.Empty; + [field: NonSerialized] + public string LowerRangeSearchText { get; set; } = string.Empty; - [field: NonSerialized] - public string LowerSearchText { get; set; } = string.Empty; + [field: NonSerialized] + public string LowerSearchText { get; set; } = string.Empty; - [field: NonSerialized] - public Regex RangeRex { get; set; } + [field: NonSerialized] + public Regex RangeRex { get; set; } - [field: NonSerialized] - public Regex Rex { get; set; } + [field: NonSerialized] + public Regex Rex { get; set; } - #endregion + #endregion - #region Public methods + #region Public methods - /// - /// Returns a new FilterParams object with the current columnizer set to the one used in this object. - /// - /// - public FilterParams CloneWithCurrentColumnizer() - { - FilterParams newParams = Clone(); - newParams.Init(); - // removed cloning of columnizer for filtering, because this causes issues with columnizers that hold internal states (like CsvColumnizer) - // newParams.currentColumnizer = Util.CloneColumnizer(this.currentColumnizer); - newParams.CurrentColumnizer = CurrentColumnizer; - return newParams; - } + /// + /// Returns a new FilterParams object with the current columnizer set to the one used in this object. + /// + /// + public FilterParams CloneWithCurrentColumnizer() + { + FilterParams newParams = Clone(); + newParams.Init(); + // removed cloning of columnizer for filtering, because this causes issues with columnizers that hold internal states (like CsvColumnizer) + // newParams.currentColumnizer = Util.CloneColumnizer(this.currentColumnizer); + newParams.CurrentColumnizer = CurrentColumnizer; + return newParams; + } - // call after deserialization! - public void Init() - { - LastNonEmptyCols = []; - LowerRangeSearchText = RangeSearchText.ToLower(); - LowerSearchText = SearchText.ToLower(); - LastLine = string.Empty; - } + // call after deserialization! + public void Init() + { + LastNonEmptyCols = []; + LowerRangeSearchText = RangeSearchText.ToLower(); + LowerSearchText = SearchText.ToLower(); + LastLine = string.Empty; + } - // Reset before a new search - public void Reset() - { - LastNonEmptyCols.Clear(); - IsInRange = false; - } + // Reset before a new search + public void Reset() + { + LastNonEmptyCols.Clear(); + IsInRange = false; + } - public void CreateRegex() + public void CreateRegex() + { + if (SearchText != null) { - if (SearchText != null) - { - Rex = new Regex(SearchText, IsCaseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase); - } - if (RangeSearchText != null && IsRangeSearch) - { - RangeRex = new Regex(RangeSearchText, IsCaseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase); - } + Rex = new Regex(SearchText, IsCaseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase); } - - /// - /// Shallow Copy - /// - /// - public FilterParams Clone() + if (RangeSearchText != null && IsRangeSearch) { - return (FilterParams)MemberwiseClone(); + RangeRex = new Regex(RangeSearchText, IsCaseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase); } + } - /// - /// Shallow Copy - /// - /// - object ICloneable.Clone() - { - return Clone(); - } + /// + /// Shallow Copy + /// + /// + public FilterParams Clone() + { + return (FilterParams)MemberwiseClone(); + } - #endregion + /// + /// Shallow Copy + /// + /// + object ICloneable.Clone() + { + return Clone(); } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Filter/FilterPipe.cs b/src/LogExpert.Core/Classes/Filter/FilterPipe.cs index fecae37f..e99ce716 100644 --- a/src/LogExpert.Core/Classes/Filter/FilterPipe.cs +++ b/src/LogExpert.Core/Classes/Filter/FilterPipe.cs @@ -7,193 +7,192 @@ using System.IO; using System.Text; -namespace LogExpert.Classes.Filter +namespace LogExpert.Classes.Filter; + +public class FilterPipe { - public class FilterPipe - { - #region Fields + #region Fields - private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); + private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); - private IList _lineMappingList = new List(); - private StreamWriter _writer; + private IList _lineMappingList = new List(); + private StreamWriter _writer; - #endregion + #endregion - #region cTor + #region cTor - public FilterPipe(FilterParams filterParams, ILogWindow logWindow) - { - FilterParams = filterParams; - LogWindow = logWindow; - IsStopped = false; - FileName = Path.GetTempFileName(); + public FilterPipe(FilterParams filterParams, ILogWindow logWindow) + { + FilterParams = filterParams; + LogWindow = logWindow; + IsStopped = false; + FileName = Path.GetTempFileName(); - _logger.Info("Created temp file: {0}", FileName); - } + _logger.Info("Created temp file: {0}", FileName); + } - #endregion + #endregion - #region Delegates + #region Delegates - public delegate void ClosedEventHandler(object sender, EventArgs e); + public delegate void ClosedEventHandler(object sender, EventArgs e); - #endregion + #endregion - #region Events + #region Events - public event ClosedEventHandler Closed; + public event ClosedEventHandler Closed; - #endregion + #endregion - #region Properties + #region Properties - public bool IsStopped { get; set; } + public bool IsStopped { get; set; } - public string FileName { get; } + public string FileName { get; } - public FilterParams FilterParams { get; } + public FilterParams FilterParams { get; } - public IList LastLinesHistoryList { get; } = new List(); + public IList LastLinesHistoryList { get; } = new List(); - public ILogWindow LogWindow { get; } + public ILogWindow LogWindow { get; } - public ILogWindow OwnLogWindow { get; set; } + public ILogWindow OwnLogWindow { get; set; } - #endregion + #endregion - #region Public methods + #region Public methods - public void OpenFile() - { - FileStream fStream = new(FileName, FileMode.Append, FileAccess.Write, FileShare.Read); - _writer = new StreamWriter(fStream, new UnicodeEncoding(false, false)); - } + public void OpenFile() + { + FileStream fStream = new(FileName, FileMode.Append, FileAccess.Write, FileShare.Read); + _writer = new StreamWriter(fStream, new UnicodeEncoding(false, false)); + } - public void CloseFile() + public void CloseFile() + { + if (_writer != null) { - if (_writer != null) - { - _writer.Close(); - _writer = null; - } + _writer.Close(); + _writer = null; } + } - public bool WriteToPipe(ILogLine textLine, int orgLineNum) + public bool WriteToPipe(ILogLine textLine, int orgLineNum) + { + try { - try + lock (FileName) { - lock (FileName) + lock (_lineMappingList) { - lock (_lineMappingList) + try + { + _writer.WriteLine(textLine.FullLine); + _lineMappingList.Add(orgLineNum); + return true; + } + catch (IOException e) { - try - { - _writer.WriteLine(textLine.FullLine); - _lineMappingList.Add(orgLineNum); - return true; - } - catch (IOException e) - { - _logger.Error(e, "writeToPipe()"); - return false; - } + _logger.Error(e, "writeToPipe()"); + return false; } } } - catch (IOException ex) - { - _logger.Error(ex, "writeToPipe(): file was closed"); - return false; - } } - - public int GetOriginalLineNum(int lineNum) + catch (IOException ex) { - lock (_lineMappingList) - { - if (_lineMappingList.Count > lineNum) - { - return _lineMappingList[lineNum]; - } - - return -1; - } + _logger.Error(ex, "writeToPipe(): file was closed"); + return false; } + } - public void ShiftLineNums(int offset) + public int GetOriginalLineNum(int lineNum) + { + lock (_lineMappingList) { - _logger.Debug("FilterPipe.ShiftLineNums() offset={0}", offset); - List newList = []; - lock (_lineMappingList) + if (_lineMappingList.Count > lineNum) { - foreach (int lineNum in _lineMappingList) - { - int line = lineNum - offset; - if (line >= 0) - { - newList.Add(line); - } - else - { - newList.Add(-1); - } - } - _lineMappingList = newList; + return _lineMappingList[lineNum]; } + + return -1; } + } - public void ClearLineNums() + public void ShiftLineNums(int offset) + { + _logger.Debug("FilterPipe.ShiftLineNums() offset={0}", offset); + List newList = []; + lock (_lineMappingList) { - _logger.Debug("FilterPipe.ClearLineNums()"); - lock (_lineMappingList) + foreach (var lineNum in _lineMappingList) { - for (int i = 0; i < _lineMappingList.Count; ++i) + var line = lineNum - offset; + if (line >= 0) { - _lineMappingList[i] = -1; + newList.Add(line); + } + else + { + newList.Add(-1); } } + _lineMappingList = newList; } + } - public void ClearLineList() + public void ClearLineNums() + { + _logger.Debug("FilterPipe.ClearLineNums()"); + lock (_lineMappingList) { - lock (_lineMappingList) + for (var i = 0; i < _lineMappingList.Count; ++i) { - _lineMappingList.Clear(); + _lineMappingList[i] = -1; } } + } - public void RecreateTempFile() + public void ClearLineList() + { + lock (_lineMappingList) { - lock (_lineMappingList) - { - _lineMappingList = new List(); - } - lock (FileName) - { - CloseFile(); - // trunc file - FileStream fStream = new(FileName, FileMode.Truncate, FileAccess.Write, FileShare.Read); - fStream.SetLength(0); - fStream.Close(); - } + _lineMappingList.Clear(); } + } - public void CloseAndDisconnect() + public void RecreateTempFile() + { + lock (_lineMappingList) + { + _lineMappingList = new List(); + } + lock (FileName) { - ClearLineList(); - OnClosed(); + CloseFile(); + // trunc file + FileStream fStream = new(FileName, FileMode.Truncate, FileAccess.Write, FileShare.Read); + fStream.SetLength(0); + fStream.Close(); } + } - #endregion + public void CloseAndDisconnect() + { + ClearLineList(); + OnClosed(); + } - #region Private Methods + #endregion - private void OnClosed() - { - Closed?.Invoke(this, EventArgs.Empty); - } + #region Private Methods - #endregion + private void OnClosed() + { + Closed?.Invoke(this, EventArgs.Empty); } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Filter/FilterStarter.cs b/src/LogExpert.Core/Classes/Filter/FilterStarter.cs index c3956c6d..7a2ba26a 100644 --- a/src/LogExpert.Core/Classes/Filter/FilterStarter.cs +++ b/src/LogExpert.Core/Classes/Filter/FilterStarter.cs @@ -3,219 +3,218 @@ using NLog; -namespace LogExpert.Classes.Filter -{ - public delegate void ProgressCallback (int lineCount); +namespace LogExpert.Classes.Filter; - public class FilterStarter - { - #region Fields +public delegate void ProgressCallback (int lineCount); - private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); +public class FilterStarter +{ + #region Fields - private readonly ColumnizerCallback _callback; - private readonly SortedDictionary _filterHitDict; - private readonly List _filterReadyList; - private readonly SortedDictionary _filterResultDict; + private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); - private readonly List _filterWorkerList; + private readonly ColumnizerCallback _callback; + private readonly SortedDictionary _filterHitDict; + private readonly List _filterReadyList; + private readonly SortedDictionary _filterResultDict; - private readonly SortedDictionary _lastFilterLinesDict; + private readonly List _filterWorkerList; - private ProgressCallback _progressCallback; - private int _progressLineCount; - private bool _shouldStop; + private readonly SortedDictionary _lastFilterLinesDict; - #endregion + private ProgressCallback _progressCallback; + private int _progressLineCount; + private bool _shouldStop; - #region cTor + #endregion - public FilterStarter (ColumnizerCallback callback, int minThreads) - { - _callback = callback; - FilterResultLines = []; - LastFilterLinesList = []; - FilterHitList = []; - _filterReadyList = []; - _filterWorkerList = []; - _filterHitDict = []; - _filterResultDict = []; - _lastFilterLinesDict = []; - ThreadCount = Environment.ProcessorCount * 4; - ThreadCount = minThreads; - ThreadPool.GetMinThreads(out _, out var completion); - ThreadPool.SetMinThreads(minThreads, completion); - ThreadPool.GetMaxThreads(out _, out _); - } + #region cTor + + public FilterStarter (ColumnizerCallback callback, int minThreads) + { + _callback = callback; + FilterResultLines = []; + LastFilterLinesList = []; + FilterHitList = []; + _filterReadyList = []; + _filterWorkerList = []; + _filterHitDict = []; + _filterResultDict = []; + _lastFilterLinesDict = []; + ThreadCount = Environment.ProcessorCount * 4; + ThreadCount = minThreads; + ThreadPool.GetMinThreads(out _, out var completion); + ThreadPool.SetMinThreads(minThreads, completion); + ThreadPool.GetMaxThreads(out _, out _); + } - #endregion + #endregion - #region Properties + #region Properties - public List FilterResultLines { get; set; } + public List FilterResultLines { get; set; } - public List LastFilterLinesList { get; set; } + public List LastFilterLinesList { get; set; } - public List FilterHitList { get; set; } + public List FilterHitList { get; set; } - public int ThreadCount { get; set; } + public int ThreadCount { get; set; } - #endregion + #endregion - #region Public methods + #region Public methods - public async void DoFilter (FilterParams filterParams, int startLine, int maxCount, ProgressCallback progressCallback) + public async void DoFilter (FilterParams filterParams, int startLine, int maxCount, ProgressCallback progressCallback) + { + FilterResultLines.Clear(); + LastFilterLinesList.Clear(); + FilterHitList.Clear(); + _filterHitDict.Clear(); + _filterReadyList.Clear(); + _filterResultDict.Clear(); + _lastFilterLinesDict.Clear(); + _filterWorkerList.Clear(); + _shouldStop = false; + + var interval = maxCount / ThreadCount; + + if (interval < 1) { - FilterResultLines.Clear(); - LastFilterLinesList.Clear(); - FilterHitList.Clear(); - _filterHitDict.Clear(); - _filterReadyList.Clear(); - _filterResultDict.Clear(); - _lastFilterLinesDict.Clear(); - _filterWorkerList.Clear(); - _shouldStop = false; - - int interval = maxCount / ThreadCount; - - if (interval < 1) - { - interval = 1; - } + interval = 1; + } - int workStartLine = startLine; - List handleList = []; - _progressLineCount = 0; - _progressCallback = progressCallback; - while (workStartLine < startLine + maxCount) + var workStartLine = startLine; + List handleList = []; + _progressLineCount = 0; + _progressCallback = progressCallback; + while (workStartLine < startLine + maxCount) + { + if (workStartLine + interval > maxCount) { - if (workStartLine + interval > maxCount) + interval = maxCount - workStartLine; + if (interval == 0) { - interval = maxCount - workStartLine; - if (interval == 0) - { - break; - } + break; } - _logger.Info("FilterStarter starts worker for line {0}, lineCount {1}", workStartLine, interval); - - await Task.Run(() => DoWork(filterParams, workStartLine, interval, ThreadProgressCallback)).ContinueWith(FilterDoneCallback); - workStartLine += interval; } + _logger.Info("FilterStarter starts worker for line {0}, lineCount {1}", workStartLine, interval); - WaitHandle[] handles = [.. handleList]; - // wait for worker threads completion - if (handles.Length > 0) - { - WaitHandle.WaitAll(handles); - } + await Task.Run(() => DoWork(filterParams, workStartLine, interval, ThreadProgressCallback)).ContinueWith(FilterDoneCallback); + workStartLine += interval; + } - MergeResults(); + WaitHandle[] handles = [.. handleList]; + // wait for worker threads completion + if (handles.Length > 0) + { + WaitHandle.WaitAll(handles); } - /// - /// Requests the FilterStarter to stop all filter threads. Call this from another thread (e.g. GUI). The function returns - /// immediately without waiting for filter end. - /// - public void CancelFilter () + MergeResults(); + } + + /// + /// Requests the FilterStarter to stop all filter threads. Call this from another thread (e.g. GUI). The function returns + /// immediately without waiting for filter end. + /// + public void CancelFilter () + { + _shouldStop = true; + lock (_filterWorkerList) { - _shouldStop = true; - lock (_filterWorkerList) + _logger.Info("Filter cancel requested. Stopping all {0} threads.", _filterWorkerList.Count); + foreach (Filter filter in _filterWorkerList) { - _logger.Info("Filter cancel requested. Stopping all {0} threads.", _filterWorkerList.Count); - foreach (Filter filter in _filterWorkerList) - { - filter.ShouldCancel = true; - } + filter.ShouldCancel = true; } } + } - #endregion + #endregion - #region Private Methods + #region Private Methods - private void ThreadProgressCallback (int lineCount) + private void ThreadProgressCallback (int lineCount) + { + var count = Interlocked.Add(ref _progressLineCount, lineCount); + _progressCallback(count); + } + + private Filter DoWork (FilterParams filterParams, int startLine, int maxCount, ProgressCallback progressCallback) + { + _logger.Info("Started Filter worker [{0}] for line {1}", Environment.CurrentManagedThreadId, startLine); + + // Give every thread own copies of ColumnizerCallback and FilterParams, because the state of the objects changes while filtering + FilterParams threadFilterParams = filterParams.CloneWithCurrentColumnizer(); + ColumnizerCallback threadColumnizerCallback = _callback.CreateCopy(); + + Filter filter = new(threadColumnizerCallback); + lock (_filterWorkerList) { - int count = Interlocked.Add(ref _progressLineCount, lineCount); - _progressCallback(count); + _filterWorkerList.Add(filter); } - private Filter DoWork (FilterParams filterParams, int startLine, int maxCount, ProgressCallback progressCallback) + if (_shouldStop) { - _logger.Info("Started Filter worker [{0}] for line {1}", Environment.CurrentManagedThreadId, startLine); + return filter; + } - // Give every thread own copies of ColumnizerCallback and FilterParams, because the state of the objects changes while filtering - FilterParams threadFilterParams = filterParams.CloneWithCurrentColumnizer(); - ColumnizerCallback threadColumnizerCallback = _callback.CreateCopy(); + _ = filter.DoFilter(threadFilterParams, startLine, maxCount, progressCallback); + _logger.Info("Filter worker [{0}] for line {1} has completed.", Thread.CurrentThread.ManagedThreadId, startLine); - Filter filter = new(threadColumnizerCallback); - lock (_filterWorkerList) - { - _filterWorkerList.Add(filter); - } + lock (_filterReadyList) + { + _filterReadyList.Add(filter); + } - if (_shouldStop) - { - return filter; - } + return filter; + } - _ = filter.DoFilter(threadFilterParams, startLine, maxCount, progressCallback); - _logger.Info("Filter worker [{0}] for line {1} has completed.", Thread.CurrentThread.ManagedThreadId, startLine); + private void FilterDoneCallback (Task filterTask) + { + if (filterTask.IsCompleted) + { + Filter filter = filterTask.Result; lock (_filterReadyList) { _filterReadyList.Add(filter); } - - return filter; } + } - private void FilterDoneCallback (Task filterTask) + private void MergeResults () + { + _logger.Info("Merging filter results."); + foreach (Filter filter in _filterReadyList) { - if (filterTask.IsCompleted) + foreach (var lineNum in filter.FilterHitList) { - Filter filter = filterTask.Result; - - lock (_filterReadyList) + if (!_filterHitDict.ContainsKey(lineNum)) { - _filterReadyList.Add(filter); + _filterHitDict.Add(lineNum, lineNum); } } - } - - private void MergeResults () - { - _logger.Info("Merging filter results."); - foreach (Filter filter in _filterReadyList) + foreach (var lineNum in filter.FilterResultLines) { - foreach (int lineNum in filter.FilterHitList) + if (!_filterResultDict.ContainsKey(lineNum)) { - if (!_filterHitDict.ContainsKey(lineNum)) - { - _filterHitDict.Add(lineNum, lineNum); - } + _filterResultDict.Add(lineNum, lineNum); } - foreach (int lineNum in filter.FilterResultLines) - { - if (!_filterResultDict.ContainsKey(lineNum)) - { - _filterResultDict.Add(lineNum, lineNum); - } - } - foreach (int lineNum in filter.LastFilterLinesList) + } + foreach (var lineNum in filter.LastFilterLinesList) + { + if (!_lastFilterLinesDict.ContainsKey(lineNum)) { - if (!_lastFilterLinesDict.ContainsKey(lineNum)) - { - _lastFilterLinesDict.Add(lineNum, lineNum); - } + _lastFilterLinesDict.Add(lineNum, lineNum); } } - FilterHitList.AddRange(_filterHitDict.Keys); - FilterResultLines.AddRange(_filterResultDict.Keys); - LastFilterLinesList.AddRange(_lastFilterLinesDict.Keys); - _logger.Info("Merging done."); } - - #endregion + FilterHitList.AddRange(_filterHitDict.Keys); + FilterResultLines.AddRange(_filterResultDict.Keys); + LastFilterLinesList.AddRange(_lastFilterLinesDict.Keys); + _logger.Info("Merging done."); } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Highlight/ActionEntry.cs b/src/LogExpert.Core/Classes/Highlight/ActionEntry.cs index 85442e15..7db9d052 100644 --- a/src/LogExpert.Core/Classes/Highlight/ActionEntry.cs +++ b/src/LogExpert.Core/Classes/Highlight/ActionEntry.cs @@ -1,25 +1,24 @@ -namespace LogExpert.Core.Classes.Highlight +namespace LogExpert.Core.Classes.Highlight; + +[Serializable] +public class ActionEntry : ICloneable { - [Serializable] - public class ActionEntry : ICloneable - { - #region Fields + #region Fields - public string ActionParam { get; set; } + public string ActionParam { get; set; } - public string PluginName { get; set; } + public string PluginName { get; set; } - public object Clone() + public object Clone() + { + var actionEntry = new ActionEntry { - var actionEntry = new ActionEntry - { - PluginName = PluginName, - ActionParam = ActionParam - }; + PluginName = PluginName, + ActionParam = ActionParam + }; - return actionEntry; - } - - #endregion + return actionEntry; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Highlight/HighlightEntry.cs b/src/LogExpert.Core/Classes/Highlight/HighlightEntry.cs index 19701967..aed89b99 100644 --- a/src/LogExpert.Core/Classes/Highlight/HighlightEntry.cs +++ b/src/LogExpert.Core/Classes/Highlight/HighlightEntry.cs @@ -3,105 +3,104 @@ using System.Drawing; using System.Text.RegularExpressions; -namespace LogExpert.Core.Classes.Highlight +namespace LogExpert.Core.Classes.Highlight; + +[Serializable] +[method: JsonConstructor] +public class HighlightEntry() : ICloneable { - [Serializable] - [method: JsonConstructor] - public class HighlightEntry() : ICloneable - { - #region Fields + #region Fields - [NonSerialized] private Regex regex = null; + [NonSerialized] private Regex regex = null; - private string _searchText = string.Empty; + private string _searchText = string.Empty; - #endregion Fields + #endregion Fields - #region Properties + #region Properties - public bool IsStopTail { get; set; } + public bool IsStopTail { get; set; } - public bool IsSetBookmark { get; set; } + public bool IsSetBookmark { get; set; } - public bool IsRegEx { get; set; } + public bool IsRegEx { get; set; } - public bool IsCaseSensitive { get; set; } + public bool IsCaseSensitive { get; set; } - public Color ForegroundColor { get; set; } + public Color ForegroundColor { get; set; } - public Color BackgroundColor { get; set; } + public Color BackgroundColor { get; set; } - public string SearchText + public string SearchText + { + get => _searchText; + set { - get => _searchText; - set - { - _searchText = value; - regex = null; - } + _searchText = value; + regex = null; } + } - public bool IsLedSwitch { get; set; } + public bool IsLedSwitch { get; set; } - public ActionEntry ActionEntry { get; set; } + public ActionEntry ActionEntry { get; set; } - public bool IsActionEntry { get; set; } + public bool IsActionEntry { get; set; } - public string BookmarkComment { get; set; } + public string BookmarkComment { get; set; } - public Regex Regex + public Regex Regex + { + get { - get + if (regex == null) { - if (regex == null) + if (IsRegEx) { - if (IsRegEx) - { - regex = new Regex(SearchText, IsCaseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase); - } - else - { - regex = new Regex(Regex.Escape(SearchText), IsCaseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase); - } + regex = new Regex(SearchText, IsCaseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase); + } + else + { + regex = new Regex(Regex.Escape(SearchText), IsCaseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase); } - return regex; } + return regex; } + } - public bool IsWordMatch { get; set; } + public bool IsWordMatch { get; set; } - // highlightes search result - [field: NonSerialized] - public bool IsSearchHit { get; set; } + // highlightes search result + [field: NonSerialized] + public bool IsSearchHit { get; set; } - public bool IsBold { get; set; } + public bool IsBold { get; set; } - public bool NoBackground { get; set; } + public bool NoBackground { get; set; } - public object Clone() + public object Clone() + { + var highLightEntry = new HighlightEntry { - var highLightEntry = new HighlightEntry - { - SearchText = SearchText, - ForegroundColor = ForegroundColor, - BackgroundColor = BackgroundColor, - IsRegEx = IsRegEx, - IsCaseSensitive = IsCaseSensitive, - IsLedSwitch = IsLedSwitch, - IsStopTail = IsStopTail, - IsSetBookmark = IsSetBookmark, - IsActionEntry = IsActionEntry, - ActionEntry = ActionEntry != null ? (ActionEntry)ActionEntry.Clone() : null, - IsWordMatch = IsWordMatch, - IsBold = IsBold, - BookmarkComment = BookmarkComment, - NoBackground = NoBackground, - IsSearchHit = IsSearchHit - }; - - return highLightEntry; - } - - #endregion Properties + SearchText = SearchText, + ForegroundColor = ForegroundColor, + BackgroundColor = BackgroundColor, + IsRegEx = IsRegEx, + IsCaseSensitive = IsCaseSensitive, + IsLedSwitch = IsLedSwitch, + IsStopTail = IsStopTail, + IsSetBookmark = IsSetBookmark, + IsActionEntry = IsActionEntry, + ActionEntry = ActionEntry != null ? (ActionEntry)ActionEntry.Clone() : null, + IsWordMatch = IsWordMatch, + IsBold = IsBold, + BookmarkComment = BookmarkComment, + NoBackground = NoBackground, + IsSearchHit = IsSearchHit + }; + + return highLightEntry; } + + #endregion Properties } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Highlight/HilightMatchEntry.cs b/src/LogExpert.Core/Classes/Highlight/HilightMatchEntry.cs index 21bda173..1052ac4b 100644 --- a/src/LogExpert.Core/Classes/Highlight/HilightMatchEntry.cs +++ b/src/LogExpert.Core/Classes/Highlight/HilightMatchEntry.cs @@ -1,27 +1,26 @@ -namespace LogExpert.Core.Classes.Highlight -{ - /// - /// Class for storing word-wise hilight matches. Used for colouring different matches on one line. - /// - public class HilightMatchEntry - { - #region Properties +namespace LogExpert.Core.Classes.Highlight; - public HighlightEntry HilightEntry { get; set; } +/// +/// Class for storing word-wise hilight matches. Used for colouring different matches on one line. +/// +public class HilightMatchEntry +{ + #region Properties - public int StartPos { get; set; } + public HighlightEntry HilightEntry { get; set; } - public int Length { get; set; } + public int StartPos { get; set; } - #endregion + public int Length { get; set; } - #region Public methods + #endregion - public override string ToString() - { - return $"{HilightEntry.SearchText}/{StartPos}/{Length}"; - } + #region Public methods - #endregion + public override string ToString() + { + return $"{HilightEntry.SearchText}/{StartPos}/{Length}"; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/IPC/IpcMessage.cs b/src/LogExpert.Core/Classes/IPC/IpcMessage.cs index 2549ed89..d52fd1f1 100644 --- a/src/LogExpert.Core/Classes/IPC/IpcMessage.cs +++ b/src/LogExpert.Core/Classes/IPC/IpcMessage.cs @@ -1,13 +1,12 @@ using Newtonsoft.Json.Linq; -namespace LogExpert.Core.Classes.IPC +namespace LogExpert.Core.Classes.IPC; + +public class IpcMessage { - public class IpcMessage - { - public int Version { get; set; } + public int Version { get; set; } - public IpcMessageType Type { get; set; } = IpcMessageType.Load; + public IpcMessageType Type { get; set; } = IpcMessageType.Load; - public JObject Payload { get; set; } = []; - } + public JObject Payload { get; set; } = []; } diff --git a/src/LogExpert.Core/Classes/IPC/IpcMessageType.cs b/src/LogExpert.Core/Classes/IPC/IpcMessageType.cs index cd4a4f7f..cd22d52c 100644 --- a/src/LogExpert.Core/Classes/IPC/IpcMessageType.cs +++ b/src/LogExpert.Core/Classes/IPC/IpcMessageType.cs @@ -1,9 +1,8 @@ -namespace LogExpert.Core.Classes.IPC +namespace LogExpert.Core.Classes.IPC; + +public enum IpcMessageType { - public enum IpcMessageType - { - Load, - NewWindow, - NewWindowOrLockedWindow - } + Load, + NewWindow, + NewWindowOrLockedWindow } diff --git a/src/LogExpert.Core/Classes/IPC/LoadPayload.cs b/src/LogExpert.Core/Classes/IPC/LoadPayload.cs index 6d5252a3..80e3f114 100644 --- a/src/LogExpert.Core/Classes/IPC/LoadPayload.cs +++ b/src/LogExpert.Core/Classes/IPC/LoadPayload.cs @@ -1,7 +1,6 @@ -namespace LogExpert.Core.Classes.IPC +namespace LogExpert.Core.Classes.IPC; + +public class LoadPayload { - public class LoadPayload - { - public List Files { get; set; } = []; - } + public List Files { get; set; } = []; } diff --git a/src/LogExpert.Core/Classes/Log/LogBuffer.cs b/src/LogExpert.Core/Classes/Log/LogBuffer.cs index 896ca8b3..72ee1062 100644 --- a/src/LogExpert.Core/Classes/Log/LogBuffer.cs +++ b/src/LogExpert.Core/Classes/Log/LogBuffer.cs @@ -1,124 +1,123 @@ using NLog; -namespace LogExpert.Core.Classes.Log +namespace LogExpert.Core.Classes.Log; + +public class LogBuffer { - public class LogBuffer - { - #region Fields + #region Fields - private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); + private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); #if DEBUG - private readonly IList _filePositions = new List(); // file position for every line + private readonly IList _filePositions = new List(); // file position for every line #endif - private readonly IList _logLines = new List(); - private int MAX_LINES = 500; - private long _size; + private readonly IList _logLines = new List(); + private int MAX_LINES = 500; + private long _size; - #endregion + #endregion - #region cTor + #region cTor - //public LogBuffer() { } + //public LogBuffer() { } - public LogBuffer(ILogFileInfo fileInfo, int maxLines) - { - FileInfo = fileInfo; - MAX_LINES = maxLines; - } + public LogBuffer(ILogFileInfo fileInfo, int maxLines) + { + FileInfo = fileInfo; + MAX_LINES = maxLines; + } - #endregion + #endregion - #region Properties + #region Properties - public long StartPos { set; get; } = 0; + public long StartPos { set; get; } - public long Size + public long Size + { + set { - set - { - _size = value; + _size = value; #if DEBUG - if (_filePositions.Count > 0) + if (_filePositions.Count > 0) + { + if (_size < _filePositions[_filePositions.Count - 1] - StartPos) { - if (_size < _filePositions[_filePositions.Count - 1] - StartPos) - { - _logger.Error("LogBuffer overall Size must be greater than last line file position!"); - } + _logger.Error("LogBuffer overall Size must be greater than last line file position!"); } -#endif } - get => _size; +#endif } + get => _size; + } - public int StartLine { set; get; } = 0; + public int StartLine { set; get; } - public int LineCount { get; private set; } + public int LineCount { get; private set; } - public bool IsDisposed { get; private set; } + public bool IsDisposed { get; private set; } - public ILogFileInfo FileInfo { get; set; } + public ILogFileInfo FileInfo { get; set; } - public int DroppedLinesCount { get; set; } = 0; + public int DroppedLinesCount { get; set; } - public int PrevBuffersDroppedLinesSum { get; set; } = 0; + public int PrevBuffersDroppedLinesSum { get; set; } - #endregion + #endregion - #region Public methods + #region Public methods - public void AddLine(ILogLine line, long filePos) - { - _logLines.Add(line); + public void AddLine(ILogLine line, long filePos) + { + _logLines.Add(line); #if DEBUG - _filePositions.Add(filePos); + _filePositions.Add(filePos); #endif - LineCount++; - IsDisposed = false; - } + LineCount++; + IsDisposed = false; + } - public void ClearLines() - { - _logLines.Clear(); - LineCount = 0; - } + public void ClearLines() + { + _logLines.Clear(); + LineCount = 0; + } - public void DisposeContent() - { - _logLines.Clear(); - IsDisposed = true; + public void DisposeContent() + { + _logLines.Clear(); + IsDisposed = true; #if DEBUG - DisposeCount++; + DisposeCount++; #endif - } + } - public ILogLine GetLineOfBlock(int num) + public ILogLine GetLineOfBlock(int num) + { + if (num < _logLines.Count && num >= 0) { - if (num < _logLines.Count && num >= 0) - { - return _logLines[num]; - } - - return null; + return _logLines[num]; } - #endregion + return null; + } + + #endregion #if DEBUG - public long DisposeCount { get; private set; } + public long DisposeCount { get; private set; } - public long GetFilePosForLineOfBlock(int line) + public long GetFilePosForLineOfBlock(int line) + { + if (line >= 0 && line < _filePositions.Count) { - if (line >= 0 && line < _filePositions.Count) - { - return _filePositions[line]; - } - - return -1; + return _filePositions[line]; } -#endif + return -1; } + +#endif } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Log/LogBufferCacheEntry.cs b/src/LogExpert.Core/Classes/Log/LogBufferCacheEntry.cs index 72230efc..0683012e 100644 --- a/src/LogExpert.Core/Classes/Log/LogBufferCacheEntry.cs +++ b/src/LogExpert.Core/Classes/Log/LogBufferCacheEntry.cs @@ -1,35 +1,34 @@ -namespace LogExpert.Core.Classes.Log -{ - public class LogBufferCacheEntry - { - #region Fields +namespace LogExpert.Core.Classes.Log; - #endregion +public class LogBufferCacheEntry +{ + #region Fields - #region cTor + #endregion - public LogBufferCacheEntry() - { - Touch(); - } + #region cTor - #endregion + public LogBufferCacheEntry() + { + Touch(); + } - #region Properties + #endregion - public LogBuffer LogBuffer { get; set; } + #region Properties - public long LastUseTimeStamp { get; private set; } + public LogBuffer LogBuffer { get; set; } - #endregion + public long LastUseTimeStamp { get; private set; } - #region Public methods + #endregion - public void Touch() - { - LastUseTimeStamp = Environment.TickCount & int.MaxValue; - } + #region Public methods - #endregion + public void Touch() + { + LastUseTimeStamp = Environment.TickCount & int.MaxValue; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Log/LogStreamReaderBase.cs b/src/LogExpert.Core/Classes/Log/LogStreamReaderBase.cs index 0b8c649a..d5800faf 100644 --- a/src/LogExpert.Core/Classes/Log/LogStreamReaderBase.cs +++ b/src/LogExpert.Core/Classes/Log/LogStreamReaderBase.cs @@ -3,69 +3,68 @@ using LogExpert.Core.Interface; -namespace LogExpert.Core.Classes.Log +namespace LogExpert.Core.Classes.Log; + +public abstract class LogStreamReaderBase : ILogStreamReader { - public abstract class LogStreamReaderBase : ILogStreamReader - { - #region cTor + #region cTor - protected LogStreamReaderBase() - { + protected LogStreamReaderBase() + { - } + } - ~LogStreamReaderBase() - { - Dispose(false); - } + ~LogStreamReaderBase() + { + Dispose(false); + } - #endregion + #endregion - #region Properties + #region Properties - /// - /// Current position in the stream. - /// - public abstract long Position { get; set; } + /// + /// Current position in the stream. + /// + public abstract long Position { get; set; } - public abstract bool IsBufferComplete { get; } + public abstract bool IsBufferComplete { get; } - public abstract Encoding Encoding { get; } + public abstract Encoding Encoding { get; } - /// - /// Indicates whether or not the stream reader has already been disposed. - /// - public bool IsDisposed { get; private set; } + /// + /// Indicates whether or not the stream reader has already been disposed. + /// + public bool IsDisposed { get; private set; } - #endregion + #endregion - #region Public methods + #region Public methods - /// - /// Destroy and release the current stream reader. - /// - public void Dispose() + /// + /// Destroy and release the current stream reader. + /// + public void Dispose() + { + try { - try - { - Dispose(true); - GC.SuppressFinalize(this); - } - finally - { - IsDisposed = true; - } + Dispose(true); + GC.SuppressFinalize(this); } - /// - /// Destroy and release the current stream reader. - /// - /// Specifies whether or not the managed objects should be released. - protected abstract void Dispose(bool disposing); + finally + { + IsDisposed = true; + } + } + /// + /// Destroy and release the current stream reader. + /// + /// Specifies whether or not the managed objects should be released. + protected abstract void Dispose(bool disposing); - public abstract int ReadChar(); + public abstract int ReadChar(); - public abstract string ReadLine(); + public abstract string ReadLine(); - #endregion - } + #endregion } diff --git a/src/LogExpert.Core/Classes/Log/LogfileReader.cs b/src/LogExpert.Core/Classes/Log/LogfileReader.cs index aa236303..87be8741 100644 --- a/src/LogExpert.Core/Classes/Log/LogfileReader.cs +++ b/src/LogExpert.Core/Classes/Log/LogfileReader.cs @@ -78,7 +78,7 @@ public LogfileReader (string fileName, EncodingOptions encodingOptions, bool mul LinkedList nameList = rolloverHandler.GetNameList(_pluginRegistry); ILogFileInfo fileInfo = null; - foreach (string name in nameList) + foreach (var name in nameList) { fileInfo = AddFile(name); } @@ -111,7 +111,7 @@ public LogfileReader (string[] fileNames, EncodingOptions encodingOptions, int b InitLruBuffers(); ILogFileInfo fileInfo = null; - foreach (string name in fileNames) + foreach (var name in fileNames) { fileInfo = AddFile(name); } @@ -176,11 +176,11 @@ public int LineCount public long FileSize { get; private set; } - public bool IsXmlMode { get; set; } = false; + public bool IsXmlMode { get; set; } public IXmlLogConfiguration XmlLogConfig { get; set; } - public IPreProcessColumnizer PreProcessColumnizer { get; set; } = null; + public IPreProcessColumnizer PreProcessColumnizer { get; set; } public EncodingOptions EncodingOptions { @@ -260,7 +260,7 @@ public int ShiftBuffers () { _logger.Info("ShiftBuffers() begin for {0}{1}", _fileName, IsMultiFile ? " (MultiFile)" : ""); AcquireBufferListWriterLock(); - int offset = 0; + var offset = 0; _isLineCountDirty = true; lock (_monitor) { @@ -275,7 +275,7 @@ public int ShiftBuffers () while (enumerator.MoveNext()) { ILogFileInfo logFileInfo = enumerator.Current; - string fileName = logFileInfo.FullName; + var fileName = logFileInfo.FullName; _logger.Debug("Testing file {0}", fileName); LinkedListNode node = fileNameList.Find(fileName); if (node == null) @@ -373,7 +373,7 @@ public int ShiftBuffers () _logger.Info("Deleting buffers for the watched file"); DeleteBuffersForInfo(_watchedILogFileInfo, true); - int startLine = LineCount - 1; + var startLine = LineCount - 1; _logger.Info("Re-Reading files"); foreach (ILogFileInfo ILogFileInfo in readNewILogFileInfoList) { @@ -459,7 +459,7 @@ public string GetLogFileNameForLine (int lineNum) { AcquireBufferListReaderLock(); LogBuffer logBuffer = GetBufferForLine(lineNum); - string fileName = logBuffer?.FileInfo.FullName; + var fileName = logBuffer?.FileInfo.FullName; ReleaseBufferListReaderLock(); return fileName; } @@ -486,15 +486,15 @@ public ILogFileInfo GetLogFileInfoForLine (int lineNum) /// public int GetNextMultiFileLine (int lineNum) { - int result = -1; + var result = -1; AcquireBufferListReaderLock(); LogBuffer logBuffer = GetBufferForLine(lineNum); if (logBuffer != null) { - int index = _bufferList.IndexOf(logBuffer); + var index = _bufferList.IndexOf(logBuffer); if (index != -1) { - for (int i = index; i < _bufferList.Count; ++i) + for (var i = index; i < _bufferList.Count; ++i) { if (_bufferList[i].FileInfo != logBuffer.FileInfo) { @@ -511,15 +511,15 @@ public int GetNextMultiFileLine (int lineNum) public int GetPrevMultiFileLine (int lineNum) { - int result = -1; + var result = -1; AcquireBufferListReaderLock(); LogBuffer logBuffer = GetBufferForLine(lineNum); if (logBuffer != null) { - int index = _bufferList.IndexOf(logBuffer); + var index = _bufferList.IndexOf(logBuffer); if (index != -1) { - for (int i = index; i >= 0; --i) + for (var i = index; i >= 0; --i) { if (_bufferList[i].FileInfo != logBuffer.FileInfo) { @@ -547,7 +547,7 @@ public int GetRealLineNumForVirtualLineNum (int lineNum) { AcquireBufferListReaderLock(); LogBuffer logBuffer = GetBufferForLine(lineNum); - int result = -1; + var result = -1; if (logBuffer != null) { logBuffer = GetFirstBufferForFileByLogBuffer(logBuffer); @@ -603,7 +603,7 @@ public void StopMonitoring () /// public void StopMonitoringAsync () { - Task task = Task.Run(StopMonitoring); + var task = Task.Run(StopMonitoring); //Thread stopperThread = new(new ThreadStart(StopMonitoring)) //{ @@ -711,17 +711,17 @@ public void LogBufferDiagnostic () { _logger.Info("-------- Buffer diagnostics -------"); _lruCacheDictLock.AcquireReaderLock(Timeout.Infinite); - int cacheCount = _lruCacheDict.Count; + var cacheCount = _lruCacheDict.Count; _logger.Info("LRU entries: {0}", cacheCount); _lruCacheDictLock.ReleaseReaderLock(); AcquireBufferListReaderLock(); _logger.Info("File: {0}\r\nBuffer count: {1}\r\nDisposed buffers: {2}", _fileName, _bufferList.Count, _bufferList.Count - cacheCount); - int lineNum = 0; + var lineNum = 0; long disposeSum = 0; long maxDispose = 0; long minDispose = int.MaxValue; - for (int i = 0; i < _bufferList.Count; ++i) + for (var i = 0; i < _bufferList.Count; ++i) { LogBuffer buffer = _bufferList[i]; _disposeLock.AcquireReaderLock(Timeout.Infinite); @@ -933,7 +933,7 @@ private void ReadToBufferList (ILogFileInfo logFileInfo, long filePos, int start reader.Position = filePos; _fileLength = logFileInfo.Length; - int lineNum = startLine; + var lineNum = startLine; LogBuffer logBuffer; AcquireBufferListReaderLock(); if (_bufferList.Count == 0) @@ -972,8 +972,8 @@ private void ReadToBufferList (ILogFileInfo logFileInfo, long filePos, int start Monitor.Enter(logBuffer); // Lock the buffer ReleaseBufferListReaderLock(); - int lineCount = logBuffer.LineCount; - int droppedLines = logBuffer.PrevBuffersDroppedLinesSum; + var lineCount = logBuffer.LineCount; + var droppedLines = logBuffer.PrevBuffersDroppedLinesSum; filePos = reader.Position; while (ReadLine(reader, logBuffer.StartLine + logBuffer.LineCount, logBuffer.StartLine + logBuffer.LineCount + droppedLines, out var line)) @@ -1129,9 +1129,9 @@ private void GarbageCollectLruCache () long startTime = Environment.TickCount; #endif _logger.Debug("Starting garbage collection"); - int threshold = 10; + var threshold = 10; _lruCacheDictLock.AcquireWriterLock(Timeout.Infinite); - int diff = 0; + var diff = 0; if (_lruCacheDict.Count - (_MAX_BUFFERS + threshold) > 0) { diff = _lruCacheDict.Count - _MAX_BUFFERS; @@ -1153,14 +1153,14 @@ private void GarbageCollectLruCache () // remove first entries (least usage) _disposeLock.AcquireWriterLock(Timeout.Infinite); - for (int i = 0; i < diff; ++i) + for (var i = 0; i < diff; ++i) { if (i >= useSorterList.Count) { break; } - int startLine = useSorterList.Values[i]; + var startLine = useSorterList.Values[i]; LogBufferCacheEntry entry = _lruCacheDict[startLine]; _lruCacheDict.Remove(startLine); entry.LogBuffer.DisposeContent(); @@ -1319,14 +1319,14 @@ private void ReReadBuffer (LogBuffer logBuffer) { ILogStreamReader reader = GetLogStreamReader(fileStream, EncodingOptions, UseNewReader); - long filePos = logBuffer.StartPos; + var filePos = logBuffer.StartPos; reader.Position = logBuffer.StartPos; - int maxLinesCount = logBuffer.LineCount; - int lineCount = 0; - int dropCount = logBuffer.PrevBuffersDroppedLinesSum; + var maxLinesCount = logBuffer.LineCount; + var lineCount = 0; + var dropCount = logBuffer.PrevBuffersDroppedLinesSum; logBuffer.ClearLines(); - while (ReadLine(reader, logBuffer.StartLine + logBuffer.LineCount, logBuffer.StartLine + logBuffer.LineCount + dropCount, out string line)) + while (ReadLine(reader, logBuffer.StartLine + logBuffer.LineCount, logBuffer.StartLine + logBuffer.LineCount + dropCount, out var line)) { if (lineCount >= maxLinesCount) { @@ -1391,9 +1391,9 @@ private LogBuffer GetBufferForLine (int lineNum) //} //int startIndex = lineNum / LogBuffer.MAX_LINES; // doesn't work anymore since XML buffer may contain more lines than MAX_LINES - int startIndex = 0; - int count = _bufferList.Count; - for (int i = startIndex; i < count; ++i) + var startIndex = 0; + var count = _bufferList.Count; + for (var i = startIndex; i < count; ++i) { logBuffer = _bufferList[i]; if (lineNum >= logBuffer.StartLine && lineNum < logBuffer.StartLine + logBuffer.LineCount) @@ -1432,7 +1432,7 @@ private LogBuffer GetFirstBufferForFileByLogBuffer (LogBuffer logBuffer) { ILogFileInfo info = logBuffer.FileInfo; AcquireBufferListReaderLock(); - int index = _bufferList.IndexOf(logBuffer); + var index = _bufferList.IndexOf(logBuffer); if (index == -1) { ReleaseBufferListReaderLock(); @@ -1461,7 +1461,7 @@ private void MonitorThreadProc () //IFileSystemPlugin fs = PluginRegistry.GetInstance().FindFileSystemForUri(this.watchedILogFileInfo.FullName); _logger.Info("MonitorThreadProc() for file {0}", _watchedILogFileInfo.FullName); - long oldSize = 0; + long oldSize; try { OnLoadingStarted(new LoadFileEventArgs(_fileName, 0, false, 0, false)); @@ -1481,7 +1481,7 @@ private void MonitorThreadProc () { try { - int pollInterval = _watchedILogFileInfo.PollInterval; + var pollInterval = _watchedILogFileInfo.PollInterval; //#if DEBUG // if (_logger.IsDebug) // { @@ -1551,7 +1551,7 @@ private void FileChanged () FileSize = _fileLength; } - long newSize = _fileLength; + var newSize = _fileLength; //if (this.currFileSize != newSize) { _logger.Info("file size changed. new size={0}, file: {1}", newSize, _fileName); @@ -1564,7 +1564,7 @@ private void FireChangeEvent () LogEventArgs args = new(); args.PrevFileSize = FileSize; args.PrevLineCount = LineCount; - long newSize = _fileLength; + var newSize = _fileLength; if (newSize < FileSize || _isDeleted) { _logger.Info("File was created anew: new size={0}, oldSize={1}", newSize, FileSize); @@ -1593,7 +1593,7 @@ private void FireChangeEvent () } else { - int offset = ShiftBuffers(); + var offset = ShiftBuffers(); //this.currFileSize = newSize; // removed because ShiftBuffers() calls ReadToBuffer() which will set the actual read size args.FileSize = newSize; args.LineCount = LineCount; diff --git a/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderBase.cs b/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderBase.cs index 7d567301..dd142b44 100644 --- a/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderBase.cs +++ b/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderBase.cs @@ -2,226 +2,225 @@ using System.Text; -namespace LogExpert.Core.Classes.Log +namespace LogExpert.Core.Classes.Log; + +public abstract class PositionAwareStreamReaderBase : LogStreamReaderBase { - public abstract class PositionAwareStreamReaderBase : LogStreamReaderBase - { - #region Fields + #region Fields - private const int MAX_LINE_LEN = 20000; + private const int MAX_LINE_LEN = 20000; - private static readonly Encoding[] _preambleEncodings = { Encoding.UTF8, Encoding.Unicode, Encoding.BigEndianUnicode, Encoding.UTF32 }; + private static readonly Encoding[] _preambleEncodings = [Encoding.UTF8, Encoding.Unicode, Encoding.BigEndianUnicode, Encoding.UTF32]; - private readonly BufferedStream _stream; - private readonly StreamReader _reader; + private readonly BufferedStream _stream; + private readonly StreamReader _reader; - private readonly int _preambleLength; - private readonly int _posIncPrecomputed; + private readonly int _preambleLength; + private readonly int _posIncPrecomputed; - private long _position; + private long _position; - #endregion + #endregion - #region cTor + #region cTor - protected PositionAwareStreamReaderBase(Stream stream, EncodingOptions encodingOptions) - { - _stream = new BufferedStream(stream); + protected PositionAwareStreamReaderBase(Stream stream, EncodingOptions encodingOptions) + { + _stream = new BufferedStream(stream); - _preambleLength = DetectPreambleLengthAndEncoding(out Encoding detectedEncoding); + _preambleLength = DetectPreambleLengthAndEncoding(out Encoding detectedEncoding); - Encoding usedEncoding = GetUsedEncoding(encodingOptions, detectedEncoding); - _posIncPrecomputed = GetPosIncPrecomputed(usedEncoding); + Encoding usedEncoding = GetUsedEncoding(encodingOptions, detectedEncoding); + _posIncPrecomputed = GetPosIncPrecomputed(usedEncoding); - _reader = new StreamReader(_stream, usedEncoding, true); + _reader = new StreamReader(_stream, usedEncoding, true); - Position = 0; - } + Position = 0; + } - #endregion + #endregion - #region Properties + #region Properties - /// - /// Current position in the stream. - /// - public sealed override long Position + /// + /// Current position in the stream. + /// + public sealed override long Position + { + get => _position; + set { - get => _position; - set - { - /* - * 1: Sometime commented (+Encoding.GetPreamble().Length) - * 2: Date 1.1 3207 - * 3: Error Message from Piet because of Unicode-Bugs. - * No Idea, if this is OK. - * 4: 27.07.09: Preamble-Length is now calculated in CT, because Encoding.GetPreamble().Length - * always delivers a fixed length (does not mater what kind of data) - */ - _position = value; // +Encoding.GetPreamble().Length; // 1 - //stream.Seek(pos, SeekOrigin.Begin); // 2 - //stream.Seek(pos + Encoding.GetPreamble().Length, SeekOrigin.Begin); // 3 - _stream.Seek(_position + _preambleLength, SeekOrigin.Begin); // 4 - - ResetReader(); - } + /* + * 1: Sometime commented (+Encoding.GetPreamble().Length) + * 2: Date 1.1 3207 + * 3: Error Message from Piet because of Unicode-Bugs. + * No Idea, if this is OK. + * 4: 27.07.09: Preamble-Length is now calculated in CT, because Encoding.GetPreamble().Length + * always delivers a fixed length (does not mater what kind of data) + */ + _position = value; // +Encoding.GetPreamble().Length; // 1 + //stream.Seek(pos, SeekOrigin.Begin); // 2 + //stream.Seek(pos + Encoding.GetPreamble().Length, SeekOrigin.Begin); // 3 + _stream.Seek(_position + _preambleLength, SeekOrigin.Begin); // 4 + + ResetReader(); } + } - public sealed override Encoding Encoding => _reader.CurrentEncoding; + public sealed override Encoding Encoding => _reader.CurrentEncoding; - public sealed override bool IsBufferComplete => true; + public sealed override bool IsBufferComplete => true; - //Refactor this needs to be given and should not be added like this - protected static int MaxLineLen => 500;//ConfigManager.Settings.Preferences.MaxLineLength; + //Refactor this needs to be given and should not be added like this + protected static int MaxLineLen => 500;//ConfigManager.Settings.Preferences.MaxLineLength; - #endregion + #endregion - #region Public methods + #region Public methods - /// - /// Destroy and release the current stream reader. - /// - /// Specifies whether or not the managed objects should be released. - protected override void Dispose(bool disposing) + /// + /// Destroy and release the current stream reader. + /// + /// Specifies whether or not the managed objects should be released. + protected override void Dispose(bool disposing) + { + if (disposing) { - if (disposing) - { - _stream.Dispose(); - _reader.Dispose(); - } + _stream.Dispose(); + _reader.Dispose(); } + } - //TODO This is unsafe and should be refactored - public override unsafe int ReadChar() + //TODO This is unsafe and should be refactored + public override unsafe int ReadChar() + { + //ObjectDisposedException.ThrowIf + if (IsDisposed) { - //ObjectDisposedException.ThrowIf - if (IsDisposed) - { - throw new ObjectDisposedException(ToString()); - } + throw new ObjectDisposedException(ToString()); + } - try + try + { + var readInt = _reader.Read(); + if (readInt != -1) { - int readInt = _reader.Read(); - if (readInt != -1) + var readChar = (char)readInt; + if (_posIncPrecomputed != 0) { - char readChar = (char)readInt; - if (_posIncPrecomputed != 0) - { - _position += _posIncPrecomputed; - } - else - { - _position += _reader.CurrentEncoding.GetByteCount(&readChar, 1); - } + _position += _posIncPrecomputed; + } + else + { + _position += _reader.CurrentEncoding.GetByteCount(&readChar, 1); } - return readInt; - } - catch (IOException) - { - return -1; } + return readInt; } - - protected virtual void ResetReader() + catch (IOException) { - _reader.DiscardBufferedData(); + return -1; } + } - protected StreamReader GetStreamReader() - { - return IsDisposed ? throw new ObjectDisposedException(ToString()) : _reader; - } + protected virtual void ResetReader() + { + _reader.DiscardBufferedData(); + } - protected void MovePosition(int offset) - { - _position += offset; - } + protected StreamReader GetStreamReader() + { + return IsDisposed ? throw new ObjectDisposedException(ToString()) : _reader; + } - #endregion + protected void MovePosition(int offset) + { + _position += offset; + } - #region Private Methods + #endregion - /// - /// Determines the actual number of preamble bytes in the file. - /// - /// Number of preamble bytes in the file - private int DetectPreambleLengthAndEncoding(out Encoding detectedEncoding) - { - /* - UTF-8: EF BB BF - UTF-16-Big-Endian-Byteorder: FE FF - UTF-16-Little-Endian-Byteorder: FF FE - UTF-32-Big-Endian-Byteorder: 00 00 FE FF - UTF-32-Little-Endian-Byteorder: FF FE 00 00 - */ + #region Private Methods - byte[] readPreamble = new byte[4]; + /// + /// Determines the actual number of preamble bytes in the file. + /// + /// Number of preamble bytes in the file + private int DetectPreambleLengthAndEncoding(out Encoding detectedEncoding) + { + /* + UTF-8: EF BB BF + UTF-16-Big-Endian-Byteorder: FE FF + UTF-16-Little-Endian-Byteorder: FF FE + UTF-32-Big-Endian-Byteorder: 00 00 FE FF + UTF-32-Little-Endian-Byteorder: FF FE 00 00 + */ - int readLen = _stream.Read(readPreamble, 0, 4); + var readPreamble = new byte[4]; - if (readLen >= 2) + var readLen = _stream.Read(readPreamble, 0, 4); + + if (readLen >= 2) + { + foreach (Encoding encoding in _preambleEncodings) { - foreach (Encoding encoding in _preambleEncodings) + var preamble = encoding.GetPreamble(); + var fail = false; + for (var i = 0; i < readLen && i < preamble.Length; ++i) { - byte[] preamble = encoding.GetPreamble(); - bool fail = false; - for (int i = 0; i < readLen && i < preamble.Length; ++i) + if (readPreamble[i] != preamble[i]) { - if (readPreamble[i] != preamble[i]) - { - fail = true; - break; - } + fail = true; + break; } + } - if (!fail) - { - detectedEncoding = encoding; - return preamble.Length; - } + if (!fail) + { + detectedEncoding = encoding; + return preamble.Length; } } - - // not found or less than 2 byte read - detectedEncoding = null; - - return 0; } - private Encoding GetUsedEncoding(EncodingOptions encodingOptions, Encoding detectedEncoding) - { - if (encodingOptions.Encoding != null) - { - return encodingOptions.Encoding; - } + // not found or less than 2 byte read + detectedEncoding = null; - if (detectedEncoding != null) - { - return detectedEncoding; - } + return 0; + } - return encodingOptions.DefaultEncoding ?? Encoding.Default; + private Encoding GetUsedEncoding(EncodingOptions encodingOptions, Encoding detectedEncoding) + { + if (encodingOptions.Encoding != null) + { + return encodingOptions.Encoding; } - private int GetPosIncPrecomputed(Encoding usedEncoding) + + if (detectedEncoding != null) { - switch (usedEncoding) - { - case UTF8Encoding _: - { - return 0; - } - case UnicodeEncoding _: - { - return 2; - } - default: - { - return 1; - } - } + return detectedEncoding; } - #endregion + return encodingOptions.DefaultEncoding ?? Encoding.Default; } + private int GetPosIncPrecomputed(Encoding usedEncoding) + { + switch (usedEncoding) + { + case UTF8Encoding _: + { + return 0; + } + case UnicodeEncoding _: + { + return 2; + } + default: + { + return 1; + } + } + } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderLegacy.cs b/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderLegacy.cs index c408d15f..8b8f7c9d 100644 --- a/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderLegacy.cs +++ b/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderLegacy.cs @@ -1,110 +1,109 @@ using LogExpert.Core.Entities; -namespace LogExpert.Core.Classes.Log +namespace LogExpert.Core.Classes.Log; + +public class PositionAwareStreamReaderLegacy : PositionAwareStreamReaderBase { - public class PositionAwareStreamReaderLegacy : PositionAwareStreamReaderBase - { - #region Fields + #region Fields - private readonly char[] _charBuffer = new char[MaxLineLen]; + private readonly char[] _charBuffer = new char[MaxLineLen]; - private int _charBufferPos; - private bool _crDetect; + private int _charBufferPos; + private bool _crDetect; - #endregion + #endregion - #region cTor + #region cTor - public PositionAwareStreamReaderLegacy(Stream stream, EncodingOptions encodingOptions) : base(stream, encodingOptions) - { + public PositionAwareStreamReaderLegacy(Stream stream, EncodingOptions encodingOptions) : base(stream, encodingOptions) + { - } + } + + #endregion - #endregion + #region Public methods - #region Public methods + public override string ReadLine() + { + int readInt; - public override string ReadLine() + while (-1 != (readInt = ReadChar())) { - int readInt; + var readChar = (char)readInt; - while (-1 != (readInt = ReadChar())) + switch (readChar) { - char readChar = (char)readInt; - - switch (readChar) - { - case '\n': + case '\n': + { + _crDetect = false; + return GetLineAndResetCharBufferPos(); + } + case '\r': + { + if (_crDetect) { - _crDetect = false; return GetLineAndResetCharBufferPos(); } - case '\r': - { - if (_crDetect) - { - return GetLineAndResetCharBufferPos(); - } - _crDetect = true; - break; - } - default: + _crDetect = true; + break; + } + default: + { + if (_crDetect) { - if (_crDetect) - { - _crDetect = false; - string line = GetLineAndResetCharBufferPos(); - AppendToCharBuffer(readChar); - return line; - } - + _crDetect = false; + var line = GetLineAndResetCharBufferPos(); AppendToCharBuffer(readChar); - break; + return line; } - } - } - string result = GetLineAndResetCharBufferPos(); - if (readInt == -1 && result.Length == 0 && !_crDetect) - { - return null; // EOF + AppendToCharBuffer(readChar); + break; + } } - _crDetect = false; - return result; } - protected override void ResetReader() + var result = GetLineAndResetCharBufferPos(); + if (readInt == -1 && result.Length == 0 && !_crDetect) { - ResetCharBufferPos(); - - base.ResetReader(); + return null; // EOF } + _crDetect = false; + return result; + } - #endregion + protected override void ResetReader() + { + ResetCharBufferPos(); - #region Private Methods + base.ResetReader(); + } - private string GetLineAndResetCharBufferPos() - { - string result = new(_charBuffer, 0, _charBufferPos); - ResetCharBufferPos(); - return result; - } + #endregion - private void AppendToCharBuffer(char readChar) - { - if (_charBufferPos < MaxLineLen) - { - _charBuffer[_charBufferPos++] = readChar; - } - } + #region Private Methods + + private string GetLineAndResetCharBufferPos() + { + string result = new(_charBuffer, 0, _charBufferPos); + ResetCharBufferPos(); + return result; + } - private void ResetCharBufferPos() + private void AppendToCharBuffer(char readChar) + { + if (_charBufferPos < MaxLineLen) { - _charBufferPos = 0; + _charBuffer[_charBufferPos++] = readChar; } + } - #endregion + private void ResetCharBufferPos() + { + _charBufferPos = 0; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderSystem.cs b/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderSystem.cs index 28495436..354703a0 100644 --- a/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderSystem.cs +++ b/src/LogExpert.Core/Classes/Log/PositionAwareStreamReaderSystem.cs @@ -1,95 +1,94 @@ using LogExpert.Core.Entities; -namespace LogExpert.Core.Classes.Log +namespace LogExpert.Core.Classes.Log; + +/// +/// This class is responsible for reading line from the log file. It also decodes characters with the appropriate charset encoding. +/// PositionAwareStreamReaderSystem tries a BOM detection to determine correct file offsets when directly seeking into the file (on re-loading flushed buffers). +/// UTF-8 handling is a bit slower, because after reading a character the byte length of the character must be determined. +/// Lines are read char-by-char. StreamReader.ReadLine() is not used because StreamReader cannot tell a file position. +/// +public class PositionAwareStreamReaderSystem : PositionAwareStreamReaderBase { - /// - /// This class is responsible for reading line from the log file. It also decodes characters with the appropriate charset encoding. - /// PositionAwareStreamReaderSystem tries a BOM detection to determine correct file offsets when directly seeking into the file (on re-loading flushed buffers). - /// UTF-8 handling is a bit slower, because after reading a character the byte length of the character must be determined. - /// Lines are read char-by-char. StreamReader.ReadLine() is not used because StreamReader cannot tell a file position. - /// - public class PositionAwareStreamReaderSystem : PositionAwareStreamReaderBase - { - #region Fields + #region Fields - private const int CHAR_CR = 0x0D; - private const int CHAR_LF = 0x0A; + private const int CHAR_CR = 0x0D; + private const int CHAR_LF = 0x0A; - private int _newLineSequenceLength; + private int _newLineSequenceLength; - #endregion + #endregion - #region cTor + #region cTor - public PositionAwareStreamReaderSystem(Stream stream, EncodingOptions encodingOptions) : base(stream, encodingOptions) - { + public PositionAwareStreamReaderSystem(Stream stream, EncodingOptions encodingOptions) : base(stream, encodingOptions) + { - } + } + + #endregion - #endregion + #region Public methods - #region Public methods + public override string ReadLine() + { + StreamReader reader = GetStreamReader(); - public override string ReadLine() + if (_newLineSequenceLength == 0) { - StreamReader reader = GetStreamReader(); + _newLineSequenceLength = GuessNewLineSequenceLength(reader); + } - if (_newLineSequenceLength == 0) - { - _newLineSequenceLength = GuessNewLineSequenceLength(reader); - } + var line = reader.ReadLine(); - string line = reader.ReadLine(); + if (line != null) + { + MovePosition(Encoding.GetByteCount(line) + _newLineSequenceLength); - if (line != null) + if (line.Length > MaxLineLen) { - MovePosition(Encoding.GetByteCount(line) + _newLineSequenceLength); - - if (line.Length > MaxLineLen) - { - line = line.Remove(MaxLineLen); - } + line = line.Remove(MaxLineLen); } - - return line; } - #endregion + return line; + } + + #endregion + + #region Private Methods - #region Private Methods + private int GuessNewLineSequenceLength(StreamReader reader) + { + var currentPos = Position; - private int GuessNewLineSequenceLength(StreamReader reader) + try { - long currentPos = Position; + var line = reader.ReadLine(); - try + if (line != null) { - string line = reader.ReadLine(); + Position += Encoding.GetByteCount(line); - if (line != null) + var firstChar = reader.Read(); + if (firstChar == CHAR_CR) // check \r { - Position += Encoding.GetByteCount(line); - - int firstChar = reader.Read(); - if (firstChar == CHAR_CR) // check \r + var secondChar = reader.Read(); + if (secondChar == CHAR_LF) // check \n { - int secondChar = reader.Read(); - if (secondChar == CHAR_LF) // check \n - { - return Encoding.GetByteCount("\r\n"); - } + return Encoding.GetByteCount("\r\n"); } - return Encoding.GetByteCount(((char)firstChar).ToString()); } - - return 0; + return Encoding.GetByteCount(((char)firstChar).ToString()); } - finally - { - Position = currentPos; - } - } - #endregion + return 0; + } + finally + { + Position = currentPos; + } } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs b/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs index faca9c2a..e9327051 100644 --- a/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs +++ b/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs @@ -2,236 +2,235 @@ using System.Text; using System.Text.RegularExpressions; -namespace LogExpert.Core.Classes.Log +namespace LogExpert.Core.Classes.Log; + +/* Needed info: + * - Date/time mask + * - index counters + * - counter direction (up/down) + * - counter limit + * - whether the files are shifted or not + * - whether the indexes start with zero (or n/a) on a new date period + * + * Format: + * *$D(yyyy-MM-dd)$I + * *$J(.) + * + * *(yyyy-MM-dd)[I] + * + */ + +/// +/// This class is responsible for building file names for multifile. +/// +public class RolloverFilenameBuilder { - /* Needed info: - * - Date/time mask - * - index counters - * - counter direction (up/down) - * - counter limit - * - whether the files are shifted or not - * - whether the indexes start with zero (or n/a) on a new date period - * - * Format: - * *$D(yyyy-MM-dd)$I - * *$J(.) - * - * *(yyyy-MM-dd)[I] - * - */ - - /// - /// This class is responsible for building file names for multifile. - /// - public class RolloverFilenameBuilder - { - #region Fields + #region Fields - private string _condContent; - private Group _condGroup; - private string _currentFileName; + private string _condContent; + private Group _condGroup; + private string _currentFileName; - private Group _dateGroup; + private Group _dateGroup; - //private Regex regexCond; - private DateTime _dateTime; + //private Regex regexCond; + private DateTime _dateTime; - //private DateTimeFormatInfo dateFormat; - private string _dateTimeFormat; + //private DateTimeFormatInfo dateFormat; + private string _dateTimeFormat; - private bool _hideZeroIndex; - private Group _indexGroup; - private Regex _regex; + private bool _hideZeroIndex; + private Group _indexGroup; + private Regex _regex; - #endregion + #endregion - #region cTor + #region cTor - public RolloverFilenameBuilder(string formatString) - { - ParseFormatString(formatString); - } + public RolloverFilenameBuilder(string formatString) + { + ParseFormatString(formatString); + } - #endregion + #endregion - #region Properties + #region Properties - public int Index { get; set; } + public int Index { get; set; } - public bool IsDatePattern => _dateGroup != null && _dateGroup.Success; + public bool IsDatePattern => _dateGroup != null && _dateGroup.Success; - public bool IsIndexPattern => _indexGroup != null && _indexGroup.Success; + public bool IsIndexPattern => _indexGroup != null && _indexGroup.Success; - #endregion + #endregion - #region Public methods + #region Public methods - public void SetFileName(string fileName) + public void SetFileName(string fileName) + { + _currentFileName = fileName; + Match match = _regex.Match(fileName); + if (match.Success) { - _currentFileName = fileName; - Match match = _regex.Match(fileName); - if (match.Success) + _dateGroup = match.Groups["date"]; + if (_dateGroup.Success) { - _dateGroup = match.Groups["date"]; - if (_dateGroup.Success) - { - string date = fileName.Substring(_dateGroup.Index, _dateGroup.Length); - if (DateTime.TryParseExact(date, _dateTimeFormat, DateTimeFormatInfo.InvariantInfo, - DateTimeStyles.None, - out _dateTime)) - { - } - } - _indexGroup = match.Groups["index"]; - if (_indexGroup.Success) + var date = fileName.Substring(_dateGroup.Index, _dateGroup.Length); + if (DateTime.TryParseExact(date, _dateTimeFormat, DateTimeFormatInfo.InvariantInfo, + DateTimeStyles.None, + out _dateTime)) { - Index = _indexGroup.Value.Length > 0 ? int.Parse(_indexGroup.Value) : 0; } - _condGroup = match.Groups["cond"]; } + _indexGroup = match.Groups["index"]; + if (_indexGroup.Success) + { + Index = _indexGroup.Value.Length > 0 ? int.Parse(_indexGroup.Value) : 0; + } + _condGroup = match.Groups["cond"]; } + } + + public void IncrementDate() + { + _dateTime = _dateTime.AddDays(1); + } + + public void DecrementDate() + { + _dateTime = _dateTime.AddDays(-1); + } - public void IncrementDate() - { - _dateTime = _dateTime.AddDays(1); - } - public void DecrementDate() + public string BuildFileName() + { + var fileName = _currentFileName; + if (_dateGroup != null && _dateGroup.Success) { - _dateTime = _dateTime.AddDays(-1); + var newDate = _dateTime.ToString(_dateTimeFormat, DateTimeFormatInfo.InvariantInfo); + fileName = fileName.Remove(_dateGroup.Index, _dateGroup.Length); + fileName = fileName.Insert(_dateGroup.Index, newDate); } - - public string BuildFileName() + if (_indexGroup != null && _indexGroup.Success) { - string fileName = _currentFileName; - if (_dateGroup != null && _dateGroup.Success) - { - string newDate = _dateTime.ToString(_dateTimeFormat, DateTimeFormatInfo.InvariantInfo); - fileName = fileName.Remove(_dateGroup.Index, _dateGroup.Length); - fileName = fileName.Insert(_dateGroup.Index, newDate); - } + fileName = fileName.Remove(_indexGroup.Index, _indexGroup.Length); - if (_indexGroup != null && _indexGroup.Success) + if (!_hideZeroIndex || Index > 0) { - fileName = fileName.Remove(_indexGroup.Index, _indexGroup.Length); - - if (!_hideZeroIndex || Index > 0) + var format = "D" + _indexGroup.Length; + fileName = fileName.Insert(_indexGroup.Index, Index.ToString(format)); + if (_hideZeroIndex && _condContent != null) { - string format = "D" + _indexGroup.Length; - fileName = fileName.Insert(_indexGroup.Index, Index.ToString(format)); - if (_hideZeroIndex && _condContent != null) - { - fileName = fileName.Insert(_indexGroup.Index, _condContent); - } + fileName = fileName.Insert(_indexGroup.Index, _condContent); } } - - // this.currentFileName = fileName; - // SetFileName(fileName); - return fileName; } - #endregion + // this.currentFileName = fileName; + // SetFileName(fileName); + return fileName; + } + + #endregion - #region Private Methods + #region Private Methods - private void ParseFormatString(string formatString) + private void ParseFormatString(string formatString) + { + var fmt = EscapeNonvarRegions(formatString); + var datePos = formatString.IndexOf("$D("); + if (datePos != -1) { - string fmt = EscapeNonvarRegions(formatString); - int datePos = formatString.IndexOf("$D("); - if (datePos != -1) + var endPos = formatString.IndexOf(')', datePos); + if (endPos != -1) { - int endPos = formatString.IndexOf(')', datePos); - if (endPos != -1) - { - _dateTimeFormat = formatString.Substring(datePos + 3, endPos - datePos - 3); - _dateTimeFormat = _dateTimeFormat.ToUpper(); - _dateTimeFormat = _dateTimeFormat.Replace('D', 'd').Replace('Y', 'y'); - - string dtf = _dateTimeFormat; - dtf = dtf.ToUpper(); - dtf = dtf.Replace("D", "\\d"); - dtf = dtf.Replace("Y", "\\d"); - dtf = dtf.Replace("M", "\\d"); - fmt = fmt.Remove(datePos, 2); // remove $D - fmt = fmt.Remove(datePos + 1, _dateTimeFormat.Length); // replace with regex version of format - fmt = fmt.Insert(datePos + 1, dtf); - fmt = fmt.Insert(datePos + 1, "?'date'"); // name the regex group - } + _dateTimeFormat = formatString.Substring(datePos + 3, endPos - datePos - 3); + _dateTimeFormat = _dateTimeFormat.ToUpper(); + _dateTimeFormat = _dateTimeFormat.Replace('D', 'd').Replace('Y', 'y'); + + var dtf = _dateTimeFormat; + dtf = dtf.ToUpper(); + dtf = dtf.Replace("D", "\\d"); + dtf = dtf.Replace("Y", "\\d"); + dtf = dtf.Replace("M", "\\d"); + fmt = fmt.Remove(datePos, 2); // remove $D + fmt = fmt.Remove(datePos + 1, _dateTimeFormat.Length); // replace with regex version of format + fmt = fmt.Insert(datePos + 1, dtf); + fmt = fmt.Insert(datePos + 1, "?'date'"); // name the regex group } + } - int condPos = fmt.IndexOf("$J("); - if (condPos != -1) + var condPos = fmt.IndexOf("$J("); + if (condPos != -1) + { + var endPos = fmt.IndexOf(')', condPos); + if (endPos != -1) { - int endPos = fmt.IndexOf(')', condPos); - if (endPos != -1) - { - _condContent = fmt.Substring(condPos + 3, endPos - condPos - 3); - fmt = fmt.Remove(condPos + 2, endPos - condPos - 1); - } + _condContent = fmt.Substring(condPos + 3, endPos - condPos - 3); + fmt = fmt.Remove(condPos + 2, endPos - condPos - 1); } + } - fmt = fmt.Replace("*", ".*"); - _hideZeroIndex = fmt.Contains("$J"); - fmt = fmt.Replace("$I", "(?'index'[\\d]+)"); - fmt = fmt.Replace("$J", "(?'index'[\\d]*)"); + fmt = fmt.Replace("*", ".*"); + _hideZeroIndex = fmt.Contains("$J"); + fmt = fmt.Replace("$I", "(?'index'[\\d]+)"); + fmt = fmt.Replace("$J", "(?'index'[\\d]*)"); - _regex = new Regex(fmt); - } + _regex = new Regex(fmt); + } - private string EscapeNonvarRegions(string formatString) + private string EscapeNonvarRegions(string formatString) + { + var fmt = formatString.Replace('*', '\xFFFD'); + StringBuilder result = new(); + var state = 0; + StringBuilder segment = new(); + for (var i = 0; i < fmt.Length; ++i) { - string fmt = formatString.Replace('*', '\xFFFD'); - StringBuilder result = new(); - int state = 0; - StringBuilder segment = new(); - for (int i = 0; i < fmt.Length; ++i) + switch (state) { - switch (state) - { - case 0: // looking for $ - if (fmt[i] == '$') - { - result.Append(Regex.Escape(segment.ToString())); - segment = new StringBuilder(); - state = 1; - } + case 0: // looking for $ + if (fmt[i] == '$') + { + result.Append(Regex.Escape(segment.ToString())); + segment = new StringBuilder(); + state = 1; + } + segment.Append(fmt[i]); + break; + case 1: // the char behind $ + segment.Append(fmt[i]); + result.Append(segment.ToString()); + segment = new StringBuilder(); + state = 2; + break; + case 2: // checking if ( or other char + if (fmt[i] == '(') + { segment.Append(fmt[i]); - break; - case 1: // the char behind $ + state = 3; + } + else + { segment.Append(fmt[i]); + state = 0; + } + break; + case 3: // looking for ) + segment.Append(fmt[i]); + if (fmt[i] == ')') + { result.Append(segment.ToString()); segment = new StringBuilder(); - state = 2; - break; - case 2: // checking if ( or other char - if (fmt[i] == '(') - { - segment.Append(fmt[i]); - state = 3; - } - else - { - segment.Append(fmt[i]); - state = 0; - } - break; - case 3: // looking for ) - segment.Append(fmt[i]); - if (fmt[i] == ')') - { - result.Append(segment.ToString()); - segment = new StringBuilder(); - state = 0; - } - break; - } + state = 0; + } + break; } - fmt = result.ToString().Replace('\xFFFD', '*'); - return fmt; } - - #endregion + fmt = result.ToString().Replace('\xFFFD', '*'); + return fmt; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Log/RolloverFilenameHandler.cs b/src/LogExpert.Core/Classes/Log/RolloverFilenameHandler.cs index 9880af25..673eebfe 100644 --- a/src/LogExpert.Core/Classes/Log/RolloverFilenameHandler.cs +++ b/src/LogExpert.Core/Classes/Log/RolloverFilenameHandler.cs @@ -2,109 +2,108 @@ using LogExpert.Core.Interface; using System.Collections.Generic; -namespace LogExpert.Core.Classes.Log +namespace LogExpert.Core.Classes.Log; + +/// +/// Handles rollover naming. The names built by the RolloverFilenameBuilder will be used +/// to check if the file exist. Names will be built by incrmenting an index and decrementing a date. +/// A configurable number of days in the past will be checked (date gaps may occur on days without log file activity). +/// Date checking is only performed if the format pattern contains a date format. Index checking +/// is only performed of the format pattern contains an index placeholder. +/// +public class RolloverFilenameHandler { - /// - /// Handles rollover naming. The names built by the RolloverFilenameBuilder will be used - /// to check if the file exist. Names will be built by incrmenting an index and decrementing a date. - /// A configurable number of days in the past will be checked (date gaps may occur on days without log file activity). - /// Date checking is only performed if the format pattern contains a date format. Index checking - /// is only performed of the format pattern contains an index placeholder. - /// - public class RolloverFilenameHandler - { - #region Fields + #region Fields - private readonly RolloverFilenameBuilder _filenameBuilder; - private readonly ILogFileInfo _logFileInfo; - private readonly MultiFileOptions _options; + private readonly RolloverFilenameBuilder _filenameBuilder; + private readonly ILogFileInfo _logFileInfo; + private readonly MultiFileOptions _options; - #endregion + #endregion - #region cTor + #region cTor - /// - /// Constructor. - /// - /// The complete path of the logfile - /// Multifile option (e.g. format pattern) - public RolloverFilenameHandler(ILogFileInfo logFileInfo, MultiFileOptions options) - { - _options = options; - _logFileInfo = logFileInfo; - _filenameBuilder = new RolloverFilenameBuilder(_options.FormatPattern); - _filenameBuilder.SetFileName(logFileInfo.FileName); - } + /// + /// Constructor. + /// + /// The complete path of the logfile + /// Multifile option (e.g. format pattern) + public RolloverFilenameHandler(ILogFileInfo logFileInfo, MultiFileOptions options) + { + _options = options; + _logFileInfo = logFileInfo; + _filenameBuilder = new RolloverFilenameBuilder(_options.FormatPattern); + _filenameBuilder.SetFileName(logFileInfo.FileName); + } - #endregion + #endregion - #region Public methods + #region Public methods - /// - /// Returns a list of the built file names (complete path) which also exists on disk. - /// The list is created by using the RolloverFilenameBuilder and checking for file existence. - /// The first entry in the list contains the oldest file. The last entry contains the file given - /// in the contructor. - /// - /// - public LinkedList GetNameList(IPluginRegistry pluginRegistry) + /// + /// Returns a list of the built file names (complete path) which also exists on disk. + /// The list is created by using the RolloverFilenameBuilder and checking for file existence. + /// The first entry in the list contains the oldest file. The last entry contains the file given + /// in the contructor. + /// + /// + public LinkedList GetNameList(IPluginRegistry pluginRegistry) + { + LinkedList fileList = new(); + var fileName = _filenameBuilder.BuildFileName(); + var filePath = _logFileInfo.DirectoryName + _logFileInfo.DirectorySeparatorChar + fileName; + fileList.AddFirst(filePath); + var found = true; + while (found) { - LinkedList fileList = new(); - string fileName = _filenameBuilder.BuildFileName(); - string filePath = _logFileInfo.DirectoryName + _logFileInfo.DirectorySeparatorChar + fileName; - fileList.AddFirst(filePath); - bool found = true; - while (found) + found = false; + // increment index and check if file exists + if (_filenameBuilder.IsIndexPattern) { - found = false; - // increment index and check if file exists - if (_filenameBuilder.IsIndexPattern) + _filenameBuilder.Index += 1; + fileName = _filenameBuilder.BuildFileName(); + filePath = _logFileInfo.DirectoryName + _logFileInfo.DirectorySeparatorChar + fileName;//TODO: Change to Directory.Combine + if (FileExists(filePath, pluginRegistry)) { - _filenameBuilder.Index += 1; + fileList.AddFirst(filePath); + found = true; + continue; + } + } + // if file with index isn't found or no index is in format pattern, decrement the current date + if (_filenameBuilder.IsDatePattern) + { + var tryCounter = 0; + _filenameBuilder.Index = 0; + while (tryCounter < _options.MaxDayTry) + { + _filenameBuilder.DecrementDate(); fileName = _filenameBuilder.BuildFileName(); filePath = _logFileInfo.DirectoryName + _logFileInfo.DirectorySeparatorChar + fileName;//TODO: Change to Directory.Combine if (FileExists(filePath, pluginRegistry)) { fileList.AddFirst(filePath); found = true; - continue; + break; } - } - // if file with index isn't found or no index is in format pattern, decrement the current date - if (_filenameBuilder.IsDatePattern) - { - int tryCounter = 0; - _filenameBuilder.Index = 0; - while (tryCounter < _options.MaxDayTry) - { - _filenameBuilder.DecrementDate(); - fileName = _filenameBuilder.BuildFileName(); - filePath = _logFileInfo.DirectoryName + _logFileInfo.DirectorySeparatorChar + fileName;//TODO: Change to Directory.Combine - if (FileExists(filePath, pluginRegistry)) - { - fileList.AddFirst(filePath); - found = true; - break; - } - tryCounter++; - } + tryCounter++; } } - return fileList; } + return fileList; + } - #endregion - - #region Private Methods + #endregion - private bool FileExists(string filePath, IPluginRegistry pluginRegistry) - { - IFileSystemPlugin fs = pluginRegistry.FindFileSystemForUri(filePath); - ILogFileInfo info = fs.GetLogfileInfo(filePath); - return info.FileExists; - } + #region Private Methods - #endregion + private bool FileExists(string filePath, IPluginRegistry pluginRegistry) + { + IFileSystemPlugin fs = pluginRegistry.FindFileSystemForUri(filePath); + ILogFileInfo info = fs.GetLogfileInfo(filePath); + return info.FileExists; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/ObjectClone.cs b/src/LogExpert.Core/Classes/ObjectClone.cs index 76cd00c6..9c6a352b 100644 --- a/src/LogExpert.Core/Classes/ObjectClone.cs +++ b/src/LogExpert.Core/Classes/ObjectClone.cs @@ -1,21 +1,20 @@ using System.IO; using System.Text.Json; -namespace LogExpert.Core.Classes -{ - public static class ObjectClone - { - #region Public methods +namespace LogExpert.Core.Classes; - public static T Clone(T RealObject) - { - using MemoryStream objectStream = new(); +public static class ObjectClone +{ + #region Public methods - JsonSerializer.Serialize(objectStream, RealObject); - objectStream.Seek(0, SeekOrigin.Begin); - return JsonSerializer.Deserialize(objectStream); - } + public static T Clone(T RealObject) + { + using MemoryStream objectStream = new(); - #endregion + JsonSerializer.Serialize(objectStream, RealObject); + objectStream.Seek(0, SeekOrigin.Begin); + return JsonSerializer.Deserialize(objectStream); } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/ParamParser.cs b/src/LogExpert.Core/Classes/ParamParser.cs index 10cda0f7..42fbee75 100644 --- a/src/LogExpert.Core/Classes/ParamParser.cs +++ b/src/LogExpert.Core/Classes/ParamParser.cs @@ -1,105 +1,103 @@ using System.Text; using System.Text.RegularExpressions; -namespace LogExpert.Core.Classes +namespace LogExpert.Core.Classes; + +public class ParamParser { - public class ParamParser - { - #region Fields + #region Fields - private readonly string argLine; + private readonly string argLine; - #endregion + #endregion - #region cTor + #region cTor - public ParamParser(string argTemplate) - { - argLine = argTemplate; - } + public ParamParser(string argTemplate) + { + argLine = argTemplate; + } - #endregion + #endregion - #region Public methods + #region Public methods - public string ReplaceParams(ILogLine logLine, int lineNum, string fileName) + public string ReplaceParams(ILogLine logLine, int lineNum, string fileName) + { + FileInfo fileInfo = new(fileName); + StringBuilder builder = new(argLine); + builder.Replace("%L", "" + lineNum); + builder.Replace("%P", + fileInfo.DirectoryName.Contains(" ") ? "\"" + fileInfo.DirectoryName + "\"" : fileInfo.DirectoryName); + builder.Replace("%N", fileInfo.Name.Contains(" ") ? "\"" + fileInfo.Name + "\"" : fileInfo.Name); + builder.Replace("%F", + fileInfo.FullName.Contains(" ") ? "\"" + fileInfo.FullName + "\"" : fileInfo.FullName); + builder.Replace("%E", + fileInfo.Extension.Contains(" ") ? "\"" + fileInfo.Extension + "\"" : fileInfo.Extension); + var stripped = StripExtension(fileInfo.Name); + builder.Replace("%M", stripped.Contains(" ") ? "\"" + stripped + "\"" : stripped); + var sPos = 0; + string reg; + string replace; + do { - FileInfo fileInfo = new(fileName); - StringBuilder builder = new(argLine); - builder.Replace("%L", "" + lineNum); - builder.Replace("%P", - fileInfo.DirectoryName.Contains(" ") ? "\"" + fileInfo.DirectoryName + "\"" : fileInfo.DirectoryName); - builder.Replace("%N", fileInfo.Name.Contains(" ") ? "\"" + fileInfo.Name + "\"" : fileInfo.Name); - builder.Replace("%F", - fileInfo.FullName.Contains(" ") ? "\"" + fileInfo.FullName + "\"" : fileInfo.FullName); - builder.Replace("%E", - fileInfo.Extension.Contains(" ") ? "\"" + fileInfo.Extension + "\"" : fileInfo.Extension); - string stripped = StripExtension(fileInfo.Name); - builder.Replace("%M", stripped.Contains(" ") ? "\"" + stripped + "\"" : stripped); - int sPos = 0; - string reg; - string replace; - do + reg = GetNextGroup(builder, ref sPos); + replace = GetNextGroup(builder, ref sPos); + if (reg != null && replace != null) { - reg = GetNextGroup(builder, ref sPos); - replace = GetNextGroup(builder, ref sPos); - if (reg != null && replace != null) - { - string result = Regex.Replace(logLine.FullLine, reg, replace); - builder.Insert(sPos, result); - } - } while (replace != null); - return builder.ToString(); - } + var result = Regex.Replace(logLine.FullLine, reg, replace); + builder.Insert(sPos, result); + } + } while (replace != null); + return builder.ToString(); + } - public static string StripExtension(string fileName) + public static string StripExtension(string fileName) + { + var i = fileName.LastIndexOf('.'); + if (i < 0) { - int i = fileName.LastIndexOf('.'); - if (i < 0) - { - i = fileName.Length - 1; - } - return fileName.Substring(0, i); + i = fileName.Length - 1; } + return fileName.Substring(0, i); + } - #endregion + #endregion - #region Private Methods + #region Private Methods - private string GetNextGroup(StringBuilder builder, ref int sPos) + private string GetNextGroup(StringBuilder builder, ref int sPos) + { + int ePos; + while (sPos < builder.Length) { - int count = 0; - int ePos; - while (sPos < builder.Length) + if (builder[sPos] == '{') { - if (builder[sPos] == '{') + ePos = sPos + 1; + var count = 1; + while (ePos < builder.Length) { - ePos = sPos + 1; - count = 1; - while (ePos < builder.Length) + if (builder[ePos] == '{') { - if (builder[ePos] == '{') - { - count++; - } - if (builder[ePos] == '}') - { - count--; - } - if (count == 0) - { - string reg = builder.ToString(sPos + 1, ePos - sPos - 1); - builder.Remove(sPos, ePos - sPos + 1); - return reg; - } - ePos++; + count++; } + if (builder[ePos] == '}') + { + count--; + } + if (count == 0) + { + var reg = builder.ToString(sPos + 1, ePos - sPos - 1); + builder.Remove(sPos, ePos - sPos + 1); + return reg; + } + ePos++; } - sPos++; } - return null; + sPos++; } - - #endregion + return null; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/PatternBlock.cs b/src/LogExpert.Core/Classes/PatternBlock.cs index a5a80ebe..2fc6b6ba 100644 --- a/src/LogExpert.Core/Classes/PatternBlock.cs +++ b/src/LogExpert.Core/Classes/PatternBlock.cs @@ -1,44 +1,43 @@ using System.Collections.Generic; -namespace LogExpert.Core.Classes -{ - public class QualityInfo - { - #region Fields +namespace LogExpert.Core.Classes; - public int quality; +public class QualityInfo +{ + #region Fields - #endregion - } + public int quality; - public class PatternBlock - { - #region Fields + #endregion +} - public int blockId; +public class PatternBlock +{ + #region Fields - public int endLine; + public int blockId; - // key: line num - public Dictionary qualityInfoList = []; + public int endLine; - public SortedDictionary srcLines = []; - public int startLine; - public int targetEnd; - public SortedDictionary targetLines = []; - public int targetStart; - public int weigth; + // key: line num + public Dictionary qualityInfoList = []; - #endregion + public SortedDictionary srcLines = []; + public int startLine; + public int targetEnd; + public SortedDictionary targetLines = []; + public int targetStart; + public int weigth; - #region Public methods + #endregion - public override string ToString() - { - return "srcStart=" + startLine + ", srcEnd=" + endLine + ", targetStart=" + targetStart + - ", targetEnd=" + targetEnd + ", weight=" + weigth; - } + #region Public methods - #endregion + public override string ToString() + { + return "srcStart=" + startLine + ", srcEnd=" + endLine + ", targetStart=" + targetStart + + ", targetEnd=" + targetEnd + ", weight=" + weigth; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Persister/FilterTabData.cs b/src/LogExpert.Core/Classes/Persister/FilterTabData.cs index 99ba728a..f1fc8fc6 100644 --- a/src/LogExpert.Core/Classes/Persister/FilterTabData.cs +++ b/src/LogExpert.Core/Classes/Persister/FilterTabData.cs @@ -1,11 +1,10 @@ using LogExpert.Core.Classes.Filter; -namespace LogExpert.Core.Classes.Persister +namespace LogExpert.Core.Classes.Persister; + +public class FilterTabData { - public class FilterTabData - { - public FilterParams FilterParams { get; set; } = new(); + public FilterParams FilterParams { get; set; } = new(); - public PersistenceData PersistenceData { get; set; } = new(); - } + public PersistenceData PersistenceData { get; set; } = new(); } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Persister/Persister.cs b/src/LogExpert.Core/Classes/Persister/Persister.cs index c5057224..c1bf9ce4 100644 --- a/src/LogExpert.Core/Classes/Persister/Persister.cs +++ b/src/LogExpert.Core/Classes/Persister/Persister.cs @@ -1,704 +1,661 @@ -using LogExpert.Core.Classes.Filter; +using System.Drawing; +using System.Text; +using System.Text.Json; +using System.Xml; + +using LogExpert.Core.Classes.Filter; using LogExpert.Core.Config; using LogExpert.Core.Entities; using NLog; -using System.Drawing; -using System.Text; -using System.Text.Json; -using System.Xml; +namespace LogExpert.Core.Classes.Persister; -namespace LogExpert.Core.Classes.Persister +//TODO Rewrite as json Persister, xml is outdated and difficult to parse and write +public class Persister { - public class PersistenceData + #region Fields + + private static readonly Logger _logger = LogManager.GetCurrentClassLogger(); + + #endregion + + #region Public methods + + public static string SavePersistenceData (string logFileName, PersistenceData persistenceData, Preferences preferences) { - #region Fields - - public SortedList bookmarkList = []; - public int bookmarkListPosition = 300; - public bool bookmarkListVisible = false; - public string columnizerName; - public int currentLine = -1; - public Encoding encoding; - public string fileName = null; - public bool filterAdvanced = false; - public List filterParamsList = []; - public int filterPosition = 222; - public bool filterSaveListVisible = false; - public List filterTabDataList = []; - public bool filterVisible = false; - public int firstDisplayedLine = -1; - public bool followTail = true; - public string highlightGroupName; - public int lineCount; - - public bool multiFile = false; - public int multiFileMaxDays; - public List multiFileNames = []; - public string multiFilePattern; - public SortedList rowHeightList = []; - public string sessionFileName = null; - public bool showBookmarkCommentColumn; - public string tabName = null; - - public string settingsSaveLoadLocation; - - #endregion + var fileName = persistenceData.sessionFileName ?? BuildPersisterFileName(logFileName, preferences); + + if (preferences.saveLocation == SessionSaveLocation.SameDir) + { + // make to log file in .lxp file relative + var filePart = Path.GetFileName(persistenceData.fileName); + persistenceData.fileName = filePart; + } + + Save(fileName, persistenceData); + return fileName; } - //TODO Rewrite as json Persister, xml is outdated and difficult to parse and write - public class Persister + public static string SavePersistenceDataWithFixedName (string persistenceFileName, + PersistenceData persistenceData) { - #region Fields + Save(persistenceFileName, persistenceData); + return persistenceFileName; + } - private static readonly Logger _logger = LogManager.GetCurrentClassLogger(); - #endregion + public static PersistenceData LoadPersistenceData (string logFileName, Preferences preferences) + { + var fileName = BuildPersisterFileName(logFileName, preferences); + return Load(fileName); + } - #region Public methods + public static PersistenceData LoadPersistenceDataOptionsOnly (string logFileName, Preferences preferences) + { + var fileName = BuildPersisterFileName(logFileName, preferences); + return LoadOptionsOnly(fileName); + } - public static string SavePersistenceData(string logFileName, PersistenceData persistenceData, Preferences preferences) - { - string fileName; + public static PersistenceData LoadPersistenceDataOptionsOnlyFromFixedFile (string persistenceFile) + { + return LoadOptionsOnly(persistenceFile); + } - if (persistenceData.sessionFileName != null) - { - fileName = persistenceData.sessionFileName; - } - else - { - fileName = BuildPersisterFileName(logFileName, preferences); - } - if (preferences.saveLocation == SessionSaveLocation.SameDir) - { - // make to log file in .lxp file relative - string filePart = Path.GetFileName(persistenceData.fileName); - persistenceData.fileName = filePart; - } + public static PersistenceData LoadPersistenceDataFromFixedFile (string persistenceFile) + { + return Load(persistenceFile); + } - Save(fileName, persistenceData); - return fileName; - } - public static string SavePersistenceDataWithFixedName(string persistenceFileName, - PersistenceData persistenceData) + /// + /// Loads the persistence options out of the given persistence file name. + /// + /// + /// + public static PersistenceData LoadOptionsOnly (string fileName) + { + PersistenceData persistenceData = new(); + XmlDocument xmlDoc = new(); + try { - Save(persistenceFileName, persistenceData); - return persistenceFileName; + xmlDoc.Load(fileName); } - - - public static PersistenceData LoadPersistenceData(string logFileName, Preferences preferences) + catch (IOException) { - string fileName = BuildPersisterFileName(logFileName, preferences); - return Load(fileName); + return null; } - public static PersistenceData LoadPersistenceDataOptionsOnly(string logFileName, Preferences preferences) + XmlNode fileNode = xmlDoc.SelectSingleNode("logexpert/file"); + if (fileNode != null) { - string fileName = BuildPersisterFileName(logFileName, preferences); - return LoadOptionsOnly(fileName); + var fileElement = fileNode as XmlElement; + ReadOptions(fileElement, persistenceData); + persistenceData.fileName = fileElement.GetAttribute("fileName"); + persistenceData.encoding = ReadEncoding(fileElement); } + return persistenceData; + } - public static PersistenceData LoadPersistenceDataOptionsOnlyFromFixedFile(string persistenceFile) - { - return LoadOptionsOnly(persistenceFile); - } + #endregion - public static PersistenceData LoadPersistenceDataFromFixedFile(string persistenceFile) + #region Private Methods + + private static string BuildPersisterFileName (string logFileName, Preferences preferences) + { + string dir; + string file; + + switch (preferences.saveLocation) { - return Load(persistenceFile); + case SessionSaveLocation.SameDir: + default: + { + FileInfo fileInfo = new(logFileName); + dir = fileInfo.DirectoryName; + file = fileInfo.DirectoryName + Path.DirectorySeparatorChar + fileInfo.Name + ".lxp"; + break; + } + case SessionSaveLocation.DocumentsDir: + { + dir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + + Path.DirectorySeparatorChar + + "LogExpert"; + file = dir + Path.DirectorySeparatorChar + BuildSessionFileNameFromPath(logFileName); + break; + } + case SessionSaveLocation.OwnDir: + { + dir = preferences.sessionSaveDirectory; + file = dir + Path.DirectorySeparatorChar + BuildSessionFileNameFromPath(logFileName); + break; + } + case SessionSaveLocation.ApplicationStartupDir: + { + //TODO Add Application.StartupPath as Variable + dir = string.Empty;// Application.StartupPath + Path.DirectorySeparatorChar + "sessionfiles"; + file = dir + Path.DirectorySeparatorChar + BuildSessionFileNameFromPath(logFileName); + break; + } } - - /// - /// Loads the persistence options out of the given persistence file name. - /// - /// - /// - public static PersistenceData LoadOptionsOnly(string fileName) + if (string.IsNullOrWhiteSpace(dir) == false && Directory.Exists(dir) == false) { - PersistenceData persistenceData = new(); - XmlDocument xmlDoc = new(); try { - xmlDoc.Load(fileName); - } - catch (IOException) - { - return null; + Directory.CreateDirectory(dir); } - XmlNode fileNode = xmlDoc.SelectSingleNode("logexpert/file"); - if (fileNode != null) + catch (Exception e) { - XmlElement fileElement = fileNode as XmlElement; - ReadOptions(fileElement, persistenceData); - persistenceData.fileName = fileElement.GetAttribute("fileName"); - persistenceData.encoding = ReadEncoding(fileElement); + //TODO this needs to be handled differently + //MessageBox.Show(e.Message, "LogExpert"); } - return persistenceData; } - #endregion + return file; + } - #region Private Methods + private static string BuildSessionFileNameFromPath (string logFileName) + { + var result = logFileName; + result = result.Replace(Path.DirectorySeparatorChar, '_'); + result = result.Replace(Path.AltDirectorySeparatorChar, '_'); + result = result.Replace(Path.VolumeSeparatorChar, '_'); + result += ".lxp"; + return result; + } - private static string BuildPersisterFileName(string logFileName, Preferences preferences) + private static void Save (string fileName, PersistenceData persistenceData) + { + XmlDocument xmlDoc = new(); + XmlElement rootElement = xmlDoc.CreateElement("logexpert"); + xmlDoc.AppendChild(rootElement); + XmlElement fileElement = xmlDoc.CreateElement("file"); + rootElement.AppendChild(fileElement); + fileElement.SetAttribute("fileName", persistenceData.fileName); + fileElement.SetAttribute("lineCount", "" + persistenceData.lineCount); + WriteBookmarks(xmlDoc, fileElement, persistenceData.bookmarkList); + WriteRowHeightList(xmlDoc, fileElement, persistenceData.rowHeightList); + WriteOptions(xmlDoc, fileElement, persistenceData); + WriteFilter(xmlDoc, fileElement, persistenceData.filterParamsList); + WriteFilterTabs(xmlDoc, fileElement, persistenceData.filterTabDataList); + WriteEncoding(xmlDoc, fileElement, persistenceData.encoding); + if (xmlDoc.HasChildNodes) { - string dir; - string file; - - switch (preferences.saveLocation) - { - case SessionSaveLocation.SameDir: - default: - { - FileInfo fileInfo = new(logFileName); - dir = fileInfo.DirectoryName; - file = fileInfo.DirectoryName + Path.DirectorySeparatorChar + fileInfo.Name + ".lxp"; - break; - } - case SessionSaveLocation.DocumentsDir: - { - dir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + - Path.DirectorySeparatorChar + - "LogExpert"; - file = dir + Path.DirectorySeparatorChar + BuildSessionFileNameFromPath(logFileName); - break; - } - case SessionSaveLocation.OwnDir: - { - dir = preferences.sessionSaveDirectory; - file = dir + Path.DirectorySeparatorChar + BuildSessionFileNameFromPath(logFileName); - break; - } - case SessionSaveLocation.ApplicationStartupDir: - { - //TODO Add Application.StartupPath as Variable - dir = string.Empty;// Application.StartupPath + Path.DirectorySeparatorChar + "sessionfiles"; - file = dir + Path.DirectorySeparatorChar + BuildSessionFileNameFromPath(logFileName); - break; - } - } - - if (string.IsNullOrWhiteSpace(dir) == false && Directory.Exists(dir) == false) - { - try - { - Directory.CreateDirectory(dir); - } - catch (Exception e) - { - //TODO this needs to be handled differently - //MessageBox.Show(e.Message, "LogExpert"); - } - } - return file; - } - - private static string BuildSessionFileNameFromPath(string logFileName) - { - string result = logFileName; - result = result.Replace(Path.DirectorySeparatorChar, '_'); - result = result.Replace(Path.AltDirectorySeparatorChar, '_'); - result = result.Replace(Path.VolumeSeparatorChar, '_'); - result += ".lxp"; - return result; - } - - private static void Save(string fileName, PersistenceData persistenceData) - { - XmlDocument xmlDoc = new(); - XmlElement rootElement = xmlDoc.CreateElement("logexpert"); - xmlDoc.AppendChild(rootElement); - XmlElement fileElement = xmlDoc.CreateElement("file"); - rootElement.AppendChild(fileElement); - fileElement.SetAttribute("fileName", persistenceData.fileName); - fileElement.SetAttribute("lineCount", "" + persistenceData.lineCount); - WriteBookmarks(xmlDoc, fileElement, persistenceData.bookmarkList); - WriteRowHeightList(xmlDoc, fileElement, persistenceData.rowHeightList); - WriteOptions(xmlDoc, fileElement, persistenceData); - WriteFilter(xmlDoc, fileElement, persistenceData.filterParamsList); - WriteFilterTabs(xmlDoc, fileElement, persistenceData.filterTabDataList); - WriteEncoding(xmlDoc, fileElement, persistenceData.encoding); - if (xmlDoc.HasChildNodes) - { - xmlDoc.Save(fileName); - } + xmlDoc.Save(fileName); } + } - private static void WriteEncoding(XmlDocument xmlDoc, XmlElement rootElement, Encoding encoding) + private static void WriteEncoding (XmlDocument xmlDoc, XmlElement rootElement, Encoding encoding) + { + if (encoding != null) { - if (encoding != null) - { - XmlElement encodingElement = xmlDoc.CreateElement("encoding"); - rootElement.AppendChild(encodingElement); - encodingElement.SetAttribute("name", encoding.WebName); - } + XmlElement encodingElement = xmlDoc.CreateElement("encoding"); + rootElement.AppendChild(encodingElement); + encodingElement.SetAttribute("name", encoding.WebName); } + } - private static void WriteFilterTabs(XmlDocument xmlDoc, XmlElement rootElement, List dataList) + private static void WriteFilterTabs (XmlDocument xmlDoc, XmlElement rootElement, List dataList) + { + if (dataList.Count > 0) { - if (dataList.Count > 0) - { - XmlElement filterTabsElement = xmlDoc.CreateElement("filterTabs"); - rootElement.AppendChild(filterTabsElement); - foreach (FilterTabData data in dataList) - { - PersistenceData persistenceData = data.PersistenceData; - XmlElement filterTabElement = xmlDoc.CreateElement("filterTab"); - filterTabsElement.AppendChild(filterTabElement); - WriteBookmarks(xmlDoc, filterTabElement, persistenceData.bookmarkList); - WriteRowHeightList(xmlDoc, filterTabElement, persistenceData.rowHeightList); - WriteOptions(xmlDoc, filterTabElement, persistenceData); - WriteFilter(xmlDoc, filterTabElement, persistenceData.filterParamsList); - WriteFilterTabs(xmlDoc, filterTabElement, persistenceData.filterTabDataList); - XmlElement filterElement = xmlDoc.CreateElement("tabFilter"); - filterTabElement.AppendChild(filterElement); - List filterList = [data.FilterParams]; - WriteFilter(xmlDoc, filterElement, filterList); - } + XmlElement filterTabsElement = xmlDoc.CreateElement("filterTabs"); + rootElement.AppendChild(filterTabsElement); + foreach (FilterTabData data in dataList) + { + PersistenceData persistenceData = data.PersistenceData; + XmlElement filterTabElement = xmlDoc.CreateElement("filterTab"); + filterTabsElement.AppendChild(filterTabElement); + WriteBookmarks(xmlDoc, filterTabElement, persistenceData.bookmarkList); + WriteRowHeightList(xmlDoc, filterTabElement, persistenceData.rowHeightList); + WriteOptions(xmlDoc, filterTabElement, persistenceData); + WriteFilter(xmlDoc, filterTabElement, persistenceData.filterParamsList); + WriteFilterTabs(xmlDoc, filterTabElement, persistenceData.filterTabDataList); + XmlElement filterElement = xmlDoc.CreateElement("tabFilter"); + filterTabElement.AppendChild(filterElement); + List filterList = [data.FilterParams]; + WriteFilter(xmlDoc, filterElement, filterList); } } + } - private static List ReadFilterTabs(XmlElement startNode) + private static List ReadFilterTabs (XmlElement startNode) + { + List dataList = []; + XmlNode filterTabsNode = startNode.SelectSingleNode("filterTabs"); + if (filterTabsNode != null) { - List dataList = []; - XmlNode filterTabsNode = startNode.SelectSingleNode("filterTabs"); - if (filterTabsNode != null) + XmlNodeList filterTabNodeList = filterTabsNode.ChildNodes; // all "filterTab" nodes + + foreach (XmlNode node in filterTabNodeList) { - XmlNodeList filterTabNodeList = filterTabsNode.ChildNodes; // all "filterTab" nodes + PersistenceData persistenceData = ReadPersistenceDataFromNode(node); + XmlNode filterNode = node.SelectSingleNode("tabFilter"); - foreach (XmlNode node in filterTabNodeList) + if (filterNode != null) { - PersistenceData persistenceData = ReadPersistenceDataFromNode(node); - XmlNode filterNode = node.SelectSingleNode("tabFilter"); - - if (filterNode != null) + List filterList = ReadFilter(filterNode as XmlElement); + FilterTabData data = new() { - List filterList = ReadFilter(filterNode as XmlElement); - FilterTabData data = new() - { - PersistenceData = persistenceData, - FilterParams = filterList[0] // there's only 1 - }; + PersistenceData = persistenceData, + FilterParams = filterList[0] // there's only 1 + }; - dataList.Add(data); - } + dataList.Add(data); } } - return dataList; } + return dataList; + } - private static void WriteFilter(XmlDocument xmlDoc, XmlElement rootElement, List filterList) + private static void WriteFilter (XmlDocument xmlDoc, XmlElement rootElement, List filterList) + { + XmlElement filtersElement = xmlDoc.CreateElement("filters"); + rootElement.AppendChild(filtersElement); + foreach (FilterParams filterParams in filterList) { - XmlElement filtersElement = xmlDoc.CreateElement("filters"); - rootElement.AppendChild(filtersElement); - foreach (FilterParams filterParams in filterList) - { - XmlElement filterElement = xmlDoc.CreateElement("filter"); - XmlElement paramsElement = xmlDoc.CreateElement("params"); - - MemoryStream stream = new(capacity: 200); - JsonSerializer.Serialize(stream, filterParams); - string base64Data = Convert.ToBase64String(stream.ToArray()); - paramsElement.InnerText = base64Data; - filterElement.AppendChild(paramsElement); - filtersElement.AppendChild(filterElement); - } + XmlElement filterElement = xmlDoc.CreateElement("filter"); + XmlElement paramsElement = xmlDoc.CreateElement("params"); + + MemoryStream stream = new(capacity: 200); + JsonSerializer.Serialize(stream, filterParams); + var base64Data = Convert.ToBase64String(stream.ToArray()); + paramsElement.InnerText = base64Data; + filterElement.AppendChild(paramsElement); + filtersElement.AppendChild(filterElement); } + } - private static List ReadFilter(XmlElement startNode) + private static List ReadFilter (XmlElement startNode) + { + List filterList = []; + XmlNode filtersNode = startNode.SelectSingleNode("filters"); + if (filtersNode != null) { - List filterList = []; - XmlNode filtersNode = startNode.SelectSingleNode("filters"); - if (filtersNode != null) + XmlNodeList filterNodeList = filtersNode.ChildNodes; // all "filter" nodes + foreach (XmlNode node in filterNodeList) { - XmlNodeList filterNodeList = filtersNode.ChildNodes; // all "filter" nodes - foreach (XmlNode node in filterNodeList) + foreach (XmlNode subNode in node.ChildNodes) { - foreach (XmlNode subNode in node.ChildNodes) + if (subNode.Name.Equals("params")) { - if (subNode.Name.Equals("params")) + var base64Text = subNode.InnerText; + var data = Convert.FromBase64String(base64Text); + MemoryStream stream = new(data); + + try + { + FilterParams filterParams = JsonSerializer.Deserialize(stream); + filterParams.Init(); + filterList.Add(filterParams); + } + catch (JsonException ex) { - string base64Text = subNode.InnerText; - byte[] data = Convert.FromBase64String(base64Text); - MemoryStream stream = new(data); - - try - { - FilterParams filterParams = JsonSerializer.Deserialize(stream); - filterParams.Init(); - filterList.Add(filterParams); - } - catch (JsonException ex) - { - _logger.Error($"Error while deserializing filter params. Exception Message: {ex.Message}"); - } + _logger.Error($"Error while deserializing filter params. Exception Message: {ex.Message}"); } } } } - return filterList; } + return filterList; + } - private static void WriteBookmarks(XmlDocument xmlDoc, XmlElement rootElement, - SortedList bookmarkList) + private static void WriteBookmarks (XmlDocument xmlDoc, XmlElement rootElement, + SortedList bookmarkList) + { + XmlElement bookmarksElement = xmlDoc.CreateElement("bookmarks"); + rootElement.AppendChild(bookmarksElement); + foreach (Entities.Bookmark bookmark in bookmarkList.Values) { - XmlElement bookmarksElement = xmlDoc.CreateElement("bookmarks"); - rootElement.AppendChild(bookmarksElement); - foreach (Entities.Bookmark bookmark in bookmarkList.Values) - { - XmlElement bookmarkElement = xmlDoc.CreateElement("bookmark"); - bookmarkElement.SetAttribute("line", "" + bookmark.LineNum); - XmlElement textElement = xmlDoc.CreateElement("text"); - textElement.InnerText = bookmark.Text; - XmlElement posXElement = xmlDoc.CreateElement("posX"); - XmlElement posYElement = xmlDoc.CreateElement("posY"); - posXElement.InnerText = "" + bookmark.OverlayOffset.Width; - posYElement.InnerText = "" + bookmark.OverlayOffset.Height; - bookmarkElement.AppendChild(textElement); - bookmarkElement.AppendChild(posXElement); - bookmarkElement.AppendChild(posYElement); - bookmarksElement.AppendChild(bookmarkElement); - } + XmlElement bookmarkElement = xmlDoc.CreateElement("bookmark"); + bookmarkElement.SetAttribute("line", "" + bookmark.LineNum); + XmlElement textElement = xmlDoc.CreateElement("text"); + textElement.InnerText = bookmark.Text; + XmlElement posXElement = xmlDoc.CreateElement("posX"); + XmlElement posYElement = xmlDoc.CreateElement("posY"); + posXElement.InnerText = "" + bookmark.OverlayOffset.Width; + posYElement.InnerText = "" + bookmark.OverlayOffset.Height; + bookmarkElement.AppendChild(textElement); + bookmarkElement.AppendChild(posXElement); + bookmarkElement.AppendChild(posYElement); + bookmarksElement.AppendChild(bookmarkElement); } + } - private static PersistenceData Load(string fileName) + private static PersistenceData Load (string fileName) + { + XmlDocument xmlDoc = new(); + xmlDoc.Load(fileName); + XmlNode fileNode = xmlDoc.SelectSingleNode("logexpert/file"); + PersistenceData persistenceData = new(); + if (fileNode != null) { - XmlDocument xmlDoc = new(); - xmlDoc.Load(fileName); - XmlNode fileNode = xmlDoc.SelectSingleNode("logexpert/file"); - PersistenceData persistenceData = new(); - if (fileNode != null) - { - persistenceData = ReadPersistenceDataFromNode(fileNode); - } - return persistenceData; + persistenceData = ReadPersistenceDataFromNode(fileNode); } + return persistenceData; + } - private static PersistenceData ReadPersistenceDataFromNode(XmlNode node) + private static PersistenceData ReadPersistenceDataFromNode (XmlNode node) + { + PersistenceData persistenceData = new(); + var fileElement = node as XmlElement; + persistenceData.bookmarkList = ReadBookmarks(fileElement); + persistenceData.rowHeightList = ReadRowHeightList(fileElement); + ReadOptions(fileElement, persistenceData); + persistenceData.fileName = fileElement.GetAttribute("fileName"); + var sLineCount = fileElement.GetAttribute("lineCount"); + if (sLineCount != null && sLineCount.Length > 0) { - PersistenceData persistenceData = new(); - XmlElement fileElement = node as XmlElement; - persistenceData.bookmarkList = ReadBookmarks(fileElement); - persistenceData.rowHeightList = ReadRowHeightList(fileElement); - ReadOptions(fileElement, persistenceData); - persistenceData.fileName = fileElement.GetAttribute("fileName"); - string sLineCount = fileElement.GetAttribute("lineCount"); - if (sLineCount != null && sLineCount.Length > 0) - { - persistenceData.lineCount = int.Parse(sLineCount); - } - persistenceData.filterParamsList = ReadFilter(fileElement); - persistenceData.filterTabDataList = ReadFilterTabs(fileElement); - persistenceData.encoding = ReadEncoding(fileElement); - return persistenceData; + persistenceData.lineCount = int.Parse(sLineCount); } + persistenceData.filterParamsList = ReadFilter(fileElement); + persistenceData.filterTabDataList = ReadFilterTabs(fileElement); + persistenceData.encoding = ReadEncoding(fileElement); + return persistenceData; + } - private static Encoding ReadEncoding(XmlElement fileElement) + private static Encoding ReadEncoding (XmlElement fileElement) + { + XmlNode encodingNode = fileElement.SelectSingleNode("encoding"); + if (encodingNode != null) { - XmlNode encodingNode = fileElement.SelectSingleNode("encoding"); - if (encodingNode != null) + XmlAttribute encAttr = encodingNode.Attributes["name"]; + try { - XmlAttribute encAttr = encodingNode.Attributes["name"]; - try - { - return encAttr == null ? null : Encoding.GetEncoding(encAttr.Value); - } - catch (ArgumentException e) - { - _logger.Error(e); - return Encoding.Default; - } - catch (NotSupportedException e) - { - _logger.Error(e); - return Encoding.Default; - } + return encAttr == null ? null : Encoding.GetEncoding(encAttr.Value); + } + catch (ArgumentException e) + { + _logger.Error(e); + return Encoding.Default; + } + catch (NotSupportedException e) + { + _logger.Error(e); + return Encoding.Default; } - return null; } + return null; + } - private static SortedList ReadBookmarks(XmlElement startNode) + private static SortedList ReadBookmarks (XmlElement startNode) + { + SortedList bookmarkList = []; + XmlNode boomarksNode = startNode.SelectSingleNode("bookmarks"); + if (boomarksNode != null) { - SortedList bookmarkList = []; - XmlNode boomarksNode = startNode.SelectSingleNode("bookmarks"); - if (boomarksNode != null) + XmlNodeList bookmarkNodeList = boomarksNode.ChildNodes; // all "bookmark" nodes + foreach (XmlNode node in bookmarkNodeList) { - XmlNodeList bookmarkNodeList = boomarksNode.ChildNodes; // all "bookmark" nodes - foreach (XmlNode node in bookmarkNodeList) - { - string text = null; - string posX = null; - string posY = null; - string line = null; + string text = null; + string posX = null; + string posY = null; + string line = null; - foreach (XmlAttribute attr in node.Attributes) + foreach (XmlAttribute attr in node.Attributes) + { + if (attr.Name.Equals("line")) { - if (attr.Name.Equals("line")) - { - line = attr.InnerText; - } + line = attr.InnerText; } - foreach (XmlNode subNode in node.ChildNodes) + } + foreach (XmlNode subNode in node.ChildNodes) + { + if (subNode.Name.Equals("text")) { - if (subNode.Name.Equals("text")) - { - text = subNode.InnerText; - } - else if (subNode.Name.Equals("posX")) - { - posX = subNode.InnerText; - } - else if (subNode.Name.Equals("posY")) - { - posY = subNode.InnerText; - } + text = subNode.InnerText; } - if (line == null || posX == null || posY == null) + else if (subNode.Name.Equals("posX")) { - _logger.Error("Invalid XML format for bookmark: {0}", node.InnerText); - continue; + posX = subNode.InnerText; } - int lineNum = int.Parse(line); - - Entities.Bookmark bookmark = new(lineNum) - { - OverlayOffset = new Size(int.Parse(posX), int.Parse(posY)) - }; - - if (text != null) + else if (subNode.Name.Equals("posY")) { - bookmark.Text = text; + posY = subNode.InnerText; } - bookmarkList.Add(lineNum, bookmark); } + if (line == null || posX == null || posY == null) + { + _logger.Error("Invalid XML format for bookmark: {0}", node.InnerText); + continue; + } + var lineNum = int.Parse(line); + + Entities.Bookmark bookmark = new(lineNum) + { + OverlayOffset = new Size(int.Parse(posX), int.Parse(posY)) + }; + + if (text != null) + { + bookmark.Text = text; + } + bookmarkList.Add(lineNum, bookmark); } - return bookmarkList; } + return bookmarkList; + } - private static void WriteRowHeightList(XmlDocument xmlDoc, XmlElement rootElement, SortedList rowHeightList) + private static void WriteRowHeightList (XmlDocument xmlDoc, XmlElement rootElement, SortedList rowHeightList) + { + XmlElement rowheightElement = xmlDoc.CreateElement("rowheights"); + rootElement.AppendChild(rowheightElement); + foreach (RowHeightEntry entry in rowHeightList.Values) { - XmlElement rowheightElement = xmlDoc.CreateElement("rowheights"); - rootElement.AppendChild(rowheightElement); - foreach (RowHeightEntry entry in rowHeightList.Values) - { - XmlElement entryElement = xmlDoc.CreateElement("rowheight"); - entryElement.SetAttribute("line", "" + entry.LineNum); - entryElement.SetAttribute("height", "" + entry.Height); - rowheightElement.AppendChild(entryElement); - } + XmlElement entryElement = xmlDoc.CreateElement("rowheight"); + entryElement.SetAttribute("line", "" + entry.LineNum); + entryElement.SetAttribute("height", "" + entry.Height); + rowheightElement.AppendChild(entryElement); } + } - private static SortedList ReadRowHeightList(XmlElement startNode) + private static SortedList ReadRowHeightList (XmlElement startNode) + { + SortedList rowHeightList = []; + XmlNode rowHeightsNode = startNode.SelectSingleNode("rowheights"); + if (rowHeightsNode != null) { - SortedList rowHeightList = []; - XmlNode rowHeightsNode = startNode.SelectSingleNode("rowheights"); - if (rowHeightsNode != null) + XmlNodeList rowHeightNodeList = rowHeightsNode.ChildNodes; // all "rowheight" nodes + foreach (XmlNode node in rowHeightNodeList) { - XmlNodeList rowHeightNodeList = rowHeightsNode.ChildNodes; // all "rowheight" nodes - foreach (XmlNode node in rowHeightNodeList) + string height = null; + string line = null; + foreach (XmlAttribute attr in node.Attributes) { - string height = null; - string line = null; - foreach (XmlAttribute attr in node.Attributes) + if (attr.Name.Equals("line")) { - if (attr.Name.Equals("line")) - { - line = attr.InnerText; - } - else if (attr.Name.Equals("height")) - { - height = attr.InnerText; - } + line = attr.InnerText; + } + else if (attr.Name.Equals("height")) + { + height = attr.InnerText; } - int lineNum = int.Parse(line); - int heightValue = int.Parse(height); - rowHeightList.Add(lineNum, new RowHeightEntry(lineNum, heightValue)); } + var lineNum = int.Parse(line); + var heightValue = int.Parse(height); + rowHeightList.Add(lineNum, new RowHeightEntry(lineNum, heightValue)); } - return rowHeightList; } + return rowHeightList; + } - private static void WriteOptions(XmlDocument xmlDoc, XmlElement rootElement, PersistenceData persistenceData) + private static void WriteOptions (XmlDocument xmlDoc, XmlElement rootElement, PersistenceData persistenceData) + { + XmlElement optionsElement = xmlDoc.CreateElement("options"); + rootElement.AppendChild(optionsElement); + + XmlElement element = xmlDoc.CreateElement("multifile"); + element.SetAttribute("enabled", persistenceData.multiFile ? "1" : "0"); + element.SetAttribute("pattern", persistenceData.multiFilePattern); + element.SetAttribute("maxDays", "" + persistenceData.multiFileMaxDays); + foreach (var fileName in persistenceData.multiFileNames) { - XmlElement optionsElement = xmlDoc.CreateElement("options"); - rootElement.AppendChild(optionsElement); - - XmlElement element = xmlDoc.CreateElement("multifile"); - element.SetAttribute("enabled", persistenceData.multiFile ? "1" : "0"); - element.SetAttribute("pattern", persistenceData.multiFilePattern); - element.SetAttribute("maxDays", "" + persistenceData.multiFileMaxDays); - foreach (string fileName in persistenceData.multiFileNames) - { - XmlElement entryElement = xmlDoc.CreateElement("fileEntry"); - entryElement.SetAttribute("fileName", "" + fileName); - element.AppendChild(entryElement); - } - optionsElement.AppendChild(element); - - element = xmlDoc.CreateElement("currentline"); - element.SetAttribute("line", "" + persistenceData.currentLine); - optionsElement.AppendChild(element); - - element = xmlDoc.CreateElement("firstDisplayedLine"); - element.SetAttribute("line", "" + persistenceData.firstDisplayedLine); - optionsElement.AppendChild(element); - - element = xmlDoc.CreateElement("filter"); - element.SetAttribute("visible", persistenceData.filterVisible ? "1" : "0"); - element.SetAttribute("advanced", persistenceData.filterAdvanced ? "1" : "0"); - element.SetAttribute("position", "" + persistenceData.filterPosition); - optionsElement.AppendChild(element); - - element = xmlDoc.CreateElement("bookmarklist"); - element.SetAttribute("visible", persistenceData.bookmarkListVisible ? "1" : "0"); - element.SetAttribute("position", "" + persistenceData.bookmarkListPosition); - optionsElement.AppendChild(element); - - element = xmlDoc.CreateElement("followTail"); - element.SetAttribute("enabled", persistenceData.followTail ? "1" : "0"); - optionsElement.AppendChild(element); - - element = xmlDoc.CreateElement("tab"); - element.SetAttribute("name", persistenceData.tabName); - rootElement.AppendChild(element); - - element = xmlDoc.CreateElement("columnizer"); - element.SetAttribute("name", persistenceData.columnizerName); - rootElement.AppendChild(element); - - element = xmlDoc.CreateElement("highlightGroup"); - element.SetAttribute("name", persistenceData.highlightGroupName); - rootElement.AppendChild(element); - - element = xmlDoc.CreateElement("bookmarkCommentColumn"); - element.SetAttribute("visible", persistenceData.showBookmarkCommentColumn ? "1" : "0"); - optionsElement.AppendChild(element); - - element = xmlDoc.CreateElement("filterSaveList"); - element.SetAttribute("visible", persistenceData.filterSaveListVisible ? "1" : "0"); - optionsElement.AppendChild(element); + XmlElement entryElement = xmlDoc.CreateElement("fileEntry"); + entryElement.SetAttribute("fileName", "" + fileName); + element.AppendChild(entryElement); } + optionsElement.AppendChild(element); + + element = xmlDoc.CreateElement("currentline"); + element.SetAttribute("line", "" + persistenceData.currentLine); + optionsElement.AppendChild(element); + + element = xmlDoc.CreateElement("firstDisplayedLine"); + element.SetAttribute("line", "" + persistenceData.firstDisplayedLine); + optionsElement.AppendChild(element); + + element = xmlDoc.CreateElement("filter"); + element.SetAttribute("visible", persistenceData.filterVisible ? "1" : "0"); + element.SetAttribute("advanced", persistenceData.filterAdvanced ? "1" : "0"); + element.SetAttribute("position", "" + persistenceData.filterPosition); + optionsElement.AppendChild(element); + + element = xmlDoc.CreateElement("bookmarklist"); + element.SetAttribute("visible", persistenceData.bookmarkListVisible ? "1" : "0"); + element.SetAttribute("position", "" + persistenceData.bookmarkListPosition); + optionsElement.AppendChild(element); + + element = xmlDoc.CreateElement("followTail"); + element.SetAttribute("enabled", persistenceData.followTail ? "1" : "0"); + optionsElement.AppendChild(element); + + element = xmlDoc.CreateElement("tab"); + element.SetAttribute("name", persistenceData.tabName); + rootElement.AppendChild(element); + + element = xmlDoc.CreateElement("columnizer"); + element.SetAttribute("name", persistenceData.columnizerName); + rootElement.AppendChild(element); + + element = xmlDoc.CreateElement("highlightGroup"); + element.SetAttribute("name", persistenceData.highlightGroupName); + rootElement.AppendChild(element); + + element = xmlDoc.CreateElement("bookmarkCommentColumn"); + element.SetAttribute("visible", persistenceData.showBookmarkCommentColumn ? "1" : "0"); + optionsElement.AppendChild(element); + + element = xmlDoc.CreateElement("filterSaveList"); + element.SetAttribute("visible", persistenceData.filterSaveListVisible ? "1" : "0"); + optionsElement.AppendChild(element); + } - private static void ReadOptions(XmlElement startNode, PersistenceData persistenceData) + private static void ReadOptions (XmlElement startNode, PersistenceData persistenceData) + { + XmlNode optionsNode = startNode.SelectSingleNode("options"); + var value = GetOptionsAttribute(optionsNode, "multifile", "enabled"); + persistenceData.multiFile = value != null && value.Equals("1"); + persistenceData.multiFilePattern = GetOptionsAttribute(optionsNode, "multifile", "pattern"); + value = GetOptionsAttribute(optionsNode, "multifile", "maxDays"); + try { - XmlNode optionsNode = startNode.SelectSingleNode("options"); - string value = GetOptionsAttribute(optionsNode, "multifile", "enabled"); - persistenceData.multiFile = value != null && value.Equals("1"); - persistenceData.multiFilePattern = GetOptionsAttribute(optionsNode, "multifile", "pattern"); - value = GetOptionsAttribute(optionsNode, "multifile", "maxDays"); - try - { - persistenceData.multiFileMaxDays = value != null ? short.Parse(value) : 0; - } - catch (Exception) - { - persistenceData.multiFileMaxDays = 0; - } + persistenceData.multiFileMaxDays = value != null ? short.Parse(value) : 0; + } + catch (Exception) + { + persistenceData.multiFileMaxDays = 0; + } - XmlNode multiFileNode = optionsNode.SelectSingleNode("multifile"); - if (multiFileNode != null) + XmlNode multiFileNode = optionsNode.SelectSingleNode("multifile"); + if (multiFileNode != null) + { + XmlNodeList multiFileNodeList = multiFileNode.ChildNodes; // all "fileEntry" nodes + foreach (XmlNode node in multiFileNodeList) { - XmlNodeList multiFileNodeList = multiFileNode.ChildNodes; // all "fileEntry" nodes - foreach (XmlNode node in multiFileNodeList) + string fileName = null; + foreach (XmlAttribute attr in node.Attributes) { - string fileName = null; - foreach (XmlAttribute attr in node.Attributes) + if (attr.Name.Equals("fileName")) { - if (attr.Name.Equals("fileName")) - { - fileName = attr.InnerText; - } + fileName = attr.InnerText; } - persistenceData.multiFileNames.Add(fileName); } + persistenceData.multiFileNames.Add(fileName); } + } - value = GetOptionsAttribute(optionsNode, "currentline", "line"); - if (value != null) - { - persistenceData.currentLine = int.Parse(value); - } - value = GetOptionsAttribute(optionsNode, "firstDisplayedLine", "line"); - if (value != null) - { - persistenceData.firstDisplayedLine = int.Parse(value); - } + value = GetOptionsAttribute(optionsNode, "currentline", "line"); + if (value != null) + { + persistenceData.currentLine = int.Parse(value); + } + value = GetOptionsAttribute(optionsNode, "firstDisplayedLine", "line"); + if (value != null) + { + persistenceData.firstDisplayedLine = int.Parse(value); + } - value = GetOptionsAttribute(optionsNode, "filter", "visible"); - persistenceData.filterVisible = value != null && value.Equals("1"); - value = GetOptionsAttribute(optionsNode, "filter", "advanced"); - persistenceData.filterAdvanced = value != null && value.Equals("1"); - value = GetOptionsAttribute(optionsNode, "filter", "position"); - if (value != null) - { - persistenceData.filterPosition = int.Parse(value); - } + value = GetOptionsAttribute(optionsNode, "filter", "visible"); + persistenceData.filterVisible = value != null && value.Equals("1"); + value = GetOptionsAttribute(optionsNode, "filter", "advanced"); + persistenceData.filterAdvanced = value != null && value.Equals("1"); + value = GetOptionsAttribute(optionsNode, "filter", "position"); + if (value != null) + { + persistenceData.filterPosition = int.Parse(value); + } - value = GetOptionsAttribute(optionsNode, "bookmarklist", "visible"); - persistenceData.bookmarkListVisible = value != null && value.Equals("1"); - value = GetOptionsAttribute(optionsNode, "bookmarklist", "position"); - if (value != null) - { - persistenceData.bookmarkListPosition = int.Parse(value); - } + value = GetOptionsAttribute(optionsNode, "bookmarklist", "visible"); + persistenceData.bookmarkListVisible = value != null && value.Equals("1"); + value = GetOptionsAttribute(optionsNode, "bookmarklist", "position"); + if (value != null) + { + persistenceData.bookmarkListPosition = int.Parse(value); + } - value = GetOptionsAttribute(optionsNode, "followTail", "enabled"); - persistenceData.followTail = value != null && value.Equals("1"); + value = GetOptionsAttribute(optionsNode, "followTail", "enabled"); + persistenceData.followTail = value != null && value.Equals("1"); - value = GetOptionsAttribute(optionsNode, "bookmarkCommentColumn", "visible"); - persistenceData.showBookmarkCommentColumn = value != null && value.Equals("1"); + value = GetOptionsAttribute(optionsNode, "bookmarkCommentColumn", "visible"); + persistenceData.showBookmarkCommentColumn = value != null && value.Equals("1"); - value = GetOptionsAttribute(optionsNode, "filterSaveList", "visible"); - persistenceData.filterSaveListVisible = value != null && value.Equals("1"); + value = GetOptionsAttribute(optionsNode, "filterSaveList", "visible"); + persistenceData.filterSaveListVisible = value != null && value.Equals("1"); - XmlNode tabNode = startNode.SelectSingleNode("tab"); - if (tabNode != null) - { - persistenceData.tabName = (tabNode as XmlElement).GetAttribute("name"); - } - XmlNode columnizerNode = startNode.SelectSingleNode("columnizer"); - if (columnizerNode != null) - { - persistenceData.columnizerName = (columnizerNode as XmlElement).GetAttribute("name"); - } - XmlNode highlightGroupNode = startNode.SelectSingleNode("highlightGroup"); - if (highlightGroupNode != null) - { - persistenceData.highlightGroupName = (highlightGroupNode as XmlElement).GetAttribute("name"); - } + XmlNode tabNode = startNode.SelectSingleNode("tab"); + if (tabNode != null) + { + persistenceData.tabName = (tabNode as XmlElement).GetAttribute("name"); + } + XmlNode columnizerNode = startNode.SelectSingleNode("columnizer"); + if (columnizerNode != null) + { + persistenceData.columnizerName = (columnizerNode as XmlElement).GetAttribute("name"); } + XmlNode highlightGroupNode = startNode.SelectSingleNode("highlightGroup"); + if (highlightGroupNode != null) + { + persistenceData.highlightGroupName = (highlightGroupNode as XmlElement).GetAttribute("name"); + } + } - private static string GetOptionsAttribute(XmlNode optionsNode, string elementName, string attrName) + private static string GetOptionsAttribute (XmlNode optionsNode, string elementName, string attrName) + { + XmlNode node = optionsNode.SelectSingleNode(elementName); + if (node == null) { - XmlNode node = optionsNode.SelectSingleNode(elementName); - if (node == null) - { - return null; - } - if (node is XmlElement) - { - string value = (node as XmlElement).GetAttribute(attrName); - return value; - } - else - { - return null; - } + return null; + } + if (node is XmlElement) + { + var value = (node as XmlElement).GetAttribute(attrName); + return value; + } + else + { + return null; } - - #endregion } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Persister/ProjectData.cs b/src/LogExpert.Core/Classes/Persister/ProjectData.cs index bc4df6ab..8b9dcaf3 100644 --- a/src/LogExpert.Core/Classes/Persister/ProjectData.cs +++ b/src/LogExpert.Core/Classes/Persister/ProjectData.cs @@ -1,14 +1,12 @@ -using System.Collections.Generic; +namespace LogExpert.Core.Classes.Persister; -namespace LogExpert.Core.Classes.Persister +public class ProjectData { - public class ProjectData - { - #region Fields + #region Fields - public List memberList = []; - public string tabLayoutXml = null; + public List MemberList { get; set; } = []; - #endregion - } + public string TabLayoutXml { get; set; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/Persister/ProjectPersister.cs b/src/LogExpert.Core/Classes/Persister/ProjectPersister.cs index 5e0a2948..12963b28 100644 --- a/src/LogExpert.Core/Classes/Persister/ProjectPersister.cs +++ b/src/LogExpert.Core/Classes/Persister/ProjectPersister.cs @@ -1,68 +1,67 @@ using System.Collections.Generic; using System.Xml; -namespace LogExpert.Core.Classes.Persister +namespace LogExpert.Core.Classes.Persister; + +public static class ProjectPersister { - public static class ProjectPersister - { - #region Public methods + #region Public methods - public static ProjectData LoadProjectData(string projectFileName) + public static ProjectData LoadProjectData(string projectFileName) + { + ProjectData projectData = new(); + XmlDocument xmlDoc = new(); + xmlDoc.Load(projectFileName); + XmlNodeList fileList = xmlDoc.GetElementsByTagName("member"); + foreach (XmlNode fileNode in fileList) { - ProjectData projectData = new(); - XmlDocument xmlDoc = new(); - xmlDoc.Load(projectFileName); - XmlNodeList fileList = xmlDoc.GetElementsByTagName("member"); - foreach (XmlNode fileNode in fileList) - { - XmlElement fileElement = fileNode as XmlElement; - string fileName = fileElement.GetAttribute("fileName"); - projectData.memberList.Add(fileName); - } - XmlNodeList layoutElements = xmlDoc.GetElementsByTagName("layout"); - if (layoutElements.Count > 0) - { - projectData.tabLayoutXml = layoutElements[0].InnerXml; - } - return projectData; + var fileElement = fileNode as XmlElement; + var fileName = fileElement.GetAttribute("fileName"); + projectData.MemberList.Add(fileName); } - - - public static void SaveProjectData(string projectFileName, ProjectData projectData) + XmlNodeList layoutElements = xmlDoc.GetElementsByTagName("layout"); + if (layoutElements.Count > 0) { - XmlDocument xmlDoc = new(); - XmlElement rootElement = xmlDoc.CreateElement("logexpert"); - xmlDoc.AppendChild(rootElement); - XmlElement projectElement = xmlDoc.CreateElement("project"); - rootElement.AppendChild(projectElement); - XmlElement membersElement = xmlDoc.CreateElement("members"); - projectElement.AppendChild(membersElement); - SaveProjectMembers(xmlDoc, membersElement, projectData.memberList); + projectData.TabLayoutXml = layoutElements[0].InnerXml; + } + return projectData; + } - if (projectData.tabLayoutXml != null) - { - XmlElement layoutElement = xmlDoc.CreateElement("layout"); - layoutElement.InnerXml = projectData.tabLayoutXml; - rootElement.AppendChild(layoutElement); - } - xmlDoc.Save(projectFileName); + public static void SaveProjectData(string projectFileName, ProjectData projectData) + { + XmlDocument xmlDoc = new(); + XmlElement rootElement = xmlDoc.CreateElement("logexpert"); + xmlDoc.AppendChild(rootElement); + XmlElement projectElement = xmlDoc.CreateElement("project"); + rootElement.AppendChild(projectElement); + XmlElement membersElement = xmlDoc.CreateElement("members"); + projectElement.AppendChild(membersElement); + SaveProjectMembers(xmlDoc, membersElement, projectData.MemberList); + + if (projectData.TabLayoutXml != null) + { + XmlElement layoutElement = xmlDoc.CreateElement("layout"); + layoutElement.InnerXml = projectData.TabLayoutXml; + rootElement.AppendChild(layoutElement); } - #endregion + xmlDoc.Save(projectFileName); + } + + #endregion - #region Private Methods + #region Private Methods - private static void SaveProjectMembers(XmlDocument xmlDoc, XmlNode membersNode, List memberList) + private static void SaveProjectMembers(XmlDocument xmlDoc, XmlNode membersNode, List memberList) + { + foreach (var fileName in memberList) { - foreach (string fileName in memberList) - { - XmlElement memberElement = xmlDoc.CreateElement("member"); - membersNode.AppendChild(memberElement); - memberElement.SetAttribute("fileName", fileName); - } + XmlElement memberElement = xmlDoc.CreateElement("member"); + membersNode.AppendChild(memberElement); + memberElement.SetAttribute("fileName", fileName); } - - #endregion } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/SpreadEntry.cs b/src/LogExpert.Core/Classes/SpreadEntry.cs index f83c81c2..090c4847 100644 --- a/src/LogExpert.Core/Classes/SpreadEntry.cs +++ b/src/LogExpert.Core/Classes/SpreadEntry.cs @@ -1,28 +1,27 @@ -namespace LogExpert.Core.Classes -{ - public class SpreadEntry - { - #region Fields +namespace LogExpert.Core.Classes; - public int Diff { get; set; } +public class SpreadEntry +{ + #region Fields - public DateTime Timestamp { get; set; } + public int Diff { get; set; } - public int LineNum { get; set; } + public DateTime Timestamp { get; set; } - public int Value { get; set; } + public int LineNum { get; set; } - #endregion + public int Value { get; set; } - #region cTor + #endregion - public SpreadEntry(int lineNum, int diff, DateTime timestamp) - { - LineNum = lineNum; - Diff = diff; - Timestamp = timestamp; - } + #region cTor - #endregion + public SpreadEntry(int lineNum, int diff, DateTime timestamp) + { + LineNum = lineNum; + Diff = diff; + Timestamp = timestamp; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/SysoutPipe.cs b/src/LogExpert.Core/Classes/SysoutPipe.cs index fbe40830..86460221 100644 --- a/src/LogExpert.Core/Classes/SysoutPipe.cs +++ b/src/LogExpert.Core/Classes/SysoutPipe.cs @@ -3,94 +3,93 @@ using System.Diagnostics; using System.Text; -namespace LogExpert.Core.Classes +namespace LogExpert.Core.Classes; + +public class SysoutPipe { - public class SysoutPipe - { - #region Fields + #region Fields - private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); + private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); - private readonly StreamReader sysout; - private StreamWriter writer; + private readonly StreamReader sysout; + private StreamWriter writer; - #endregion + #endregion - #region cTor + #region cTor - public SysoutPipe(StreamReader sysout) - { - this.sysout = sysout; - FileName = Path.GetTempFileName(); - _logger.Info("sysoutPipe created temp file: {0}", FileName); + public SysoutPipe(StreamReader sysout) + { + this.sysout = sysout; + FileName = Path.GetTempFileName(); + _logger.Info("sysoutPipe created temp file: {0}", FileName); - FileStream fStream = new(FileName, FileMode.Append, FileAccess.Write, FileShare.Read); - writer = new StreamWriter(fStream, Encoding.Unicode); + FileStream fStream = new(FileName, FileMode.Append, FileAccess.Write, FileShare.Read); + writer = new StreamWriter(fStream, Encoding.Unicode); - Thread thread = new(new ThreadStart(ReaderThread)) - { - IsBackground = true - }; - thread.Start(); - } + Thread thread = new(new ThreadStart(ReaderThread)) + { + IsBackground = true + }; + thread.Start(); + } - #endregion + #endregion - #region Properties + #region Properties - public string FileName { get; } + public string FileName { get; } - #endregion + #endregion - #region Public methods + #region Public methods - public void ClosePipe() - { - writer.Close(); - writer = null; - } + public void ClosePipe() + { + writer.Close(); + writer = null; + } - public void DataReceivedEventHandler(object sender, DataReceivedEventArgs e) - { - writer.WriteLine(e.Data); - } + public void DataReceivedEventHandler(object sender, DataReceivedEventArgs e) + { + writer.WriteLine(e.Data); + } - public void ProcessExitedEventHandler(object sender, System.EventArgs e) + public void ProcessExitedEventHandler(object sender, System.EventArgs e) + { + //ClosePipe(); + if (sender.GetType() == typeof(Process)) { - //ClosePipe(); - if (sender.GetType() == typeof(Process)) - { - ((Process)sender).Exited -= ProcessExitedEventHandler; - ((Process)sender).OutputDataReceived -= DataReceivedEventHandler; - } + ((Process)sender).Exited -= ProcessExitedEventHandler; + ((Process)sender).OutputDataReceived -= DataReceivedEventHandler; } + } - #endregion + #endregion - protected void ReaderThread() - { - char[] buff = new char[256]; + protected void ReaderThread() + { + var buff = new char[256]; - while (true) + while (true) + { + try { - try - { - int read = sysout.Read(buff, 0, 256); - if (read == 0) - { - break; - } - writer.Write(buff, 0, read); - } - catch (IOException e) + var read = sysout.Read(buff, 0, 256); + if (read == 0) { - _logger.Error(e); break; } + writer.Write(buff, 0, read); + } + catch (IOException e) + { + _logger.Error(e); + break; } - - ClosePipe(); } + + ClosePipe(); } } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/UsedComponents.cs b/src/LogExpert.Core/Classes/UsedComponents.cs index 39e176f4..6f62b6cd 100644 --- a/src/LogExpert.Core/Classes/UsedComponents.cs +++ b/src/LogExpert.Core/Classes/UsedComponents.cs @@ -1,20 +1,19 @@ -namespace LogExpert.Core.Classes +namespace LogExpert.Core.Classes; + +[Serializable] +public class UsedComponents { - [Serializable] - public class UsedComponents - { - public string PackageId { get; set; } + public string PackageId { get; set; } - public string PackageVersion { get; set; } + public string PackageVersion { get; set; } - public string PackageProjectUrl { get; set; } + public string PackageProjectUrl { get; set; } - public string Copyright { get; set; } + public string Copyright { get; set; } - public string Authors { get; set; } + public string Authors { get; set; } - public string License { get; set; } + public string License { get; set; } - public string LicenseUrl { get; set; } - } + public string LicenseUrl { get; set; } } diff --git a/src/LogExpert.Core/Classes/xml/XmlBlockSplitter.cs b/src/LogExpert.Core/Classes/xml/XmlBlockSplitter.cs index 8b8a643c..469f5ab2 100644 --- a/src/LogExpert.Core/Classes/xml/XmlBlockSplitter.cs +++ b/src/LogExpert.Core/Classes/xml/XmlBlockSplitter.cs @@ -4,167 +4,166 @@ using System.Xml; using System.Xml.Xsl; -namespace LogExpert.Core.Classes.xml -{ - public class XmlBlockSplitter : LogStreamReaderBase - { - #region Fields - - private static readonly string[] _splitStrings = { "\r\n", "\n", "\r" }; +namespace LogExpert.Core.Classes.xml; - private static readonly char[] _newLineChar = { '\n' }; - - private readonly XmlLogReader _reader; +public class XmlBlockSplitter : LogStreamReaderBase +{ + #region Fields - private readonly XmlParserContext _context; - private readonly XmlReaderSettings _settings; + private static readonly string[] _splitStrings = ["\r\n", "\n", "\r"]; - private readonly Queue _lineList = new(); + private static readonly char[] _newLineChar = ['\n']; - private string _stylesheet; - private XslCompiledTransform _xslt; + private readonly XmlLogReader _reader; - #endregion + private readonly XmlParserContext _context; + private readonly XmlReaderSettings _settings; - #region cTor + private readonly Queue _lineList = new(); - public XmlBlockSplitter(XmlLogReader reader, IXmlLogConfiguration xmlLogConfig) - { - _reader = reader; - _reader.StartTag = xmlLogConfig.XmlStartTag; - _reader.EndTag = xmlLogConfig.XmlEndTag; + private string _stylesheet; + private XslCompiledTransform _xslt; - Stylesheet = xmlLogConfig.Stylesheet; + #endregion - // Create the XmlNamespaceManager. - NameTable nt = new(); - XmlNamespaceManager nsmgr = new(nt); - if (xmlLogConfig.Namespace != null) - { - nsmgr.AddNamespace(xmlLogConfig.Namespace[0], xmlLogConfig.Namespace[1]); - } - // Create the XmlParserContext. - _context = new XmlParserContext(nt, nsmgr, null, XmlSpace.None); - _settings = new XmlReaderSettings(); - _settings.ConformanceLevel = ConformanceLevel.Fragment; - } + #region cTor - #endregion + public XmlBlockSplitter(XmlLogReader reader, IXmlLogConfiguration xmlLogConfig) + { + _reader = reader; + _reader.StartTag = xmlLogConfig.XmlStartTag; + _reader.EndTag = xmlLogConfig.XmlEndTag; - #region Properties + Stylesheet = xmlLogConfig.Stylesheet; - public override long Position + // Create the XmlNamespaceManager. + NameTable nt = new(); + XmlNamespaceManager nsmgr = new(nt); + if (xmlLogConfig.Namespace != null) { - get => _reader.Position; - set => _reader.Position = value; + nsmgr.AddNamespace(xmlLogConfig.Namespace[0], xmlLogConfig.Namespace[1]); } + // Create the XmlParserContext. + _context = new XmlParserContext(nt, nsmgr, null, XmlSpace.None); + _settings = new XmlReaderSettings(); + _settings.ConformanceLevel = ConformanceLevel.Fragment; + } - public override Encoding Encoding => _reader.Encoding; + #endregion - public override bool IsBufferComplete => _lineList.Count == 0; + #region Properties - public string Stylesheet - { - get => _stylesheet; - set - { - _stylesheet = value; - if (_stylesheet != null) - { - XmlReader stylesheetReader = XmlReader.Create(new StringReader(_stylesheet)); - - _xslt = new XslCompiledTransform(); - _xslt.Load(stylesheetReader); - } - else - { - _xslt = null; - } - } - } + public override long Position + { + get => _reader.Position; + set => _reader.Position = value; + } - #endregion + public override Encoding Encoding => _reader.Encoding; - #region Private Methods + public override bool IsBufferComplete => _lineList.Count == 0; - private void ParseXmlBlock(string block) + public string Stylesheet + { + get => _stylesheet; + set { + _stylesheet = value; if (_stylesheet != null) { - XmlReader xmlReader = XmlReader.Create(new StringReader(block), _settings, _context); + var stylesheetReader = XmlReader.Create(new StringReader(_stylesheet)); - xmlReader.Read(); - xmlReader.MoveToContent(); - //xmlReader.MoveToContent(); - StringWriter textWriter = new(); - - _xslt.Transform(xmlReader, null, textWriter); - string message = textWriter.ToString(); - SplitToLinesList(message); + _xslt = new XslCompiledTransform(); + _xslt.Load(stylesheetReader); } else { - SplitToLinesList(block); - //this.lineList.Add(block); // TODO: make configurable, if block has to be splitted + _xslt = null; } } + } + + #endregion - private void SplitToLinesList(string message) + #region Private Methods + + private void ParseXmlBlock(string block) + { + if (_stylesheet != null) { - const int MAX_LEN = 3000; - string[] lines = message.Split(_splitStrings, StringSplitOptions.None); - foreach (string theLine in lines) - { - string line = theLine.Trim(_newLineChar); - while (line.Length > MAX_LEN) - { - string part = line.Substring(0, MAX_LEN); - line = line.Substring(MAX_LEN); - _lineList.Enqueue(part); - } - _lineList.Enqueue(line); - } - } + var xmlReader = XmlReader.Create(new StringReader(block), _settings, _context); - #endregion + xmlReader.Read(); + xmlReader.MoveToContent(); + //xmlReader.MoveToContent(); + StringWriter textWriter = new(); - #region Public Methods + _xslt.Transform(xmlReader, null, textWriter); + var message = textWriter.ToString(); + SplitToLinesList(message); + } + else + { + SplitToLinesList(block); + //this.lineList.Add(block); // TODO: make configurable, if block has to be splitted + } + } - protected override void Dispose(bool disposing) + private void SplitToLinesList(string message) + { + const int MAX_LEN = 3000; + var lines = message.Split(_splitStrings, StringSplitOptions.None); + foreach (var theLine in lines) { - if (disposing) + var line = theLine.Trim(_newLineChar); + while (line.Length > MAX_LEN) { - _reader.Dispose(); + var part = line.Substring(0, MAX_LEN); + line = line.Substring(MAX_LEN); + _lineList.Enqueue(part); } + _lineList.Enqueue(line); } + } + + #endregion - public override int ReadChar() + #region Public Methods + + protected override void Dispose(bool disposing) + { + if (disposing) { - return _reader.ReadChar(); + _reader.Dispose(); } + } - public override string ReadLine() + public override int ReadChar() + { + return _reader.ReadChar(); + } + + public override string ReadLine() + { + if (_lineList.Count == 0) { - if (_lineList.Count == 0) + var block = _reader.ReadLine(); + if (block == null) { - string block = _reader.ReadLine(); - if (block == null) - { - return null; - } - - try - { - ParseXmlBlock(block); - } - catch (XmlException) - { - _lineList.Enqueue("[XML Parser error] " + block); - } + return null; } - return _lineList.Dequeue(); - } - #endregion + try + { + ParseXmlBlock(block); + } + catch (XmlException) + { + _lineList.Enqueue("[XML Parser error] " + block); + } + } + return _lineList.Dequeue(); } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Classes/xml/XmlLogReader.cs b/src/LogExpert.Core/Classes/xml/XmlLogReader.cs index 09da8017..9334cbbd 100644 --- a/src/LogExpert.Core/Classes/xml/XmlLogReader.cs +++ b/src/LogExpert.Core/Classes/xml/XmlLogReader.cs @@ -3,169 +3,166 @@ using System.Text; -namespace LogExpert.Core.Classes.xml +namespace LogExpert.Core.Classes.xml; + +public class XmlLogReader : LogStreamReaderBase { - public class XmlLogReader : LogStreamReaderBase - { - #region Fields + #region Fields - private readonly ILogStreamReader reader; + private readonly ILogStreamReader reader; - #endregion + #endregion - #region cTor + #region cTor - public XmlLogReader(ILogStreamReader reader) - { - this.reader = reader; - } + public XmlLogReader(ILogStreamReader reader) + { + this.reader = reader; + } - #endregion + #endregion - #region Properties + #region Properties - public override long Position - { - get => reader.Position; - set => reader.Position = value; - } + public override long Position + { + get => reader.Position; + set => reader.Position = value; + } - public override Encoding Encoding => reader.Encoding; + public override Encoding Encoding => reader.Encoding; - public override bool IsBufferComplete => reader.IsBufferComplete; + public override bool IsBufferComplete => reader.IsBufferComplete; - public string StartTag { get; set; } = " 0) { - if (--tryCounter > 0) - { - Thread.Sleep(100); - continue; - } - else - { - eof = true; - break; - } + Thread.Sleep(100); + continue; } else { - eof = true; break; } } - - char readChar = (char)readInt; - // state: - // 0 = looking for tag start - // 1 = reading into buffer as long as the read data matches the start tag - // 2 = reading into buffer while waiting for the begin of the end tag - // 3 = reading into buffer as long as data matches the end tag. stopping when tag complete - switch (state) + else { - case 0: - if (readChar == StartTag[0]) - { - //_logger.logInfo("state = 1"); - state = 1; - tagIndex = 1; - builder.Append(readChar); - } - //else - //{ - // _logger.logInfo("char: " + readChar); - //} - break; - case 1: - if (readChar == StartTag[tagIndex]) - { - builder.Append(readChar); - - if (++tagIndex >= StartTag.Length) - { - //_logger.logInfo("state = 2"); - state = 2; // start Tag complete - tagIndex = 0; - } - } - else - { - // tag doesn't match anymore - //_logger.logInfo("state = 0 [" + buffer.ToString() + readChar + "]"); - state = 0; - builder.Clear(); - } - break; - case 2: - builder.Append(readChar); + break; + } + } - if (readChar == EndTag[0]) - { - //_logger.logInfo("state = 3"); - state = 3; - tagIndex = 1; - } - break; - case 3: + var readChar = (char)readInt; + // state: + // 0 = looking for tag start + // 1 = reading into buffer as long as the read data matches the start tag + // 2 = reading into buffer while waiting for the begin of the end tag + // 3 = reading into buffer as long as data matches the end tag. stopping when tag complete + switch (state) + { + case 0: + if (readChar == StartTag[0]) + { + //_logger.logInfo("state = 1"); + state = 1; + tagIndex = 1; + builder.Append(readChar); + } + //else + //{ + // _logger.logInfo("char: " + readChar); + //} + break; + case 1: + if (readChar == StartTag[tagIndex]) + { builder.Append(readChar); - if (readChar == EndTag[tagIndex]) + if (++tagIndex >= StartTag.Length) { - tagIndex++; - if (tagIndex >= EndTag.Length) - { - blockComplete = true; - break; - } + //_logger.logInfo("state = 2"); + state = 2; // start Tag complete + tagIndex = 0; } - else + } + else + { + // tag doesn't match anymore + //_logger.logInfo("state = 0 [" + buffer.ToString() + readChar + "]"); + state = 0; + builder.Clear(); + } + break; + case 2: + builder.Append(readChar); + + if (readChar == EndTag[0]) + { + //_logger.logInfo("state = 3"); + state = 3; + tagIndex = 1; + } + break; + case 3: + builder.Append(readChar); + + if (readChar == EndTag[tagIndex]) + { + tagIndex++; + if (tagIndex >= EndTag.Length) { - //_logger.logInfo("state = 2"); - state = 2; + blockComplete = true; + break; } - break; - } + } + else + { + //_logger.logInfo("state = 2"); + state = 2; + } + break; } - - return blockComplete ? builder.ToString() : null; } - #endregion + return blockComplete ? builder.ToString() : null; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Config/ColorEntry.cs b/src/LogExpert.Core/Config/ColorEntry.cs index 6a2dc251..ceeaf244 100644 --- a/src/LogExpert.Core/Config/ColorEntry.cs +++ b/src/LogExpert.Core/Config/ColorEntry.cs @@ -4,27 +4,26 @@ #endregion -namespace LogExpert.Core.Config +namespace LogExpert.Core.Config; + +[Serializable] +public class ColorEntry { - [Serializable] - public class ColorEntry - { - #region cTor + #region cTor - public ColorEntry(string fileName, Color color) - { - FileName = fileName; - Color = color; - } + public ColorEntry(string fileName, Color color) + { + FileName = fileName; + Color = color; + } - #endregion + #endregion - public Color Color { get; } + public Color Color { get; } - public string FileName { get; } + public string FileName { get; } - #region Fields + #region Fields - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Config/ColorMode.cs b/src/LogExpert.Core/Config/ColorMode.cs index ac7c3690..b8297b95 100644 --- a/src/LogExpert.Core/Config/ColorMode.cs +++ b/src/LogExpert.Core/Config/ColorMode.cs @@ -1,78 +1,77 @@ using System.Drawing; using System.Runtime.InteropServices; -namespace LogExpert.Core.Config +namespace LogExpert.Core.Config; + +public static class ColorMode { - public static class ColorMode - { - // Bright Theme - // https://paletton.com/#uid=15-0u0k00sH00kJ0pq+00RL00RL - private static readonly Color BrightBookmarkDefaultSystemColor = SystemColors.Control; // Important: only supports SystemColors - private static readonly Color LessBrightBackgroundColor = Color.FromArgb(208, 205, 206); - private static readonly Color BrightBackgroundColor = Color.FromArgb(221, 221, 221); - private static readonly Color BrighterBackgroundColor = Color.FromArgb(253, 253, 253); - private static readonly Color BrightForeColor = Color.FromArgb(0, 0, 0); + // Bright Theme + // https://paletton.com/#uid=15-0u0k00sH00kJ0pq+00RL00RL + private static readonly Color BrightBookmarkDefaultSystemColor = SystemColors.Control; // Important: only supports SystemColors + private static readonly Color LessBrightBackgroundColor = Color.FromArgb(208, 205, 206); + private static readonly Color BrightBackgroundColor = Color.FromArgb(221, 221, 221); + private static readonly Color BrighterBackgroundColor = Color.FromArgb(253, 253, 253); + private static readonly Color BrightForeColor = Color.FromArgb(0, 0, 0); - // Dark Theme - // https://paletton.com/#uid=15-0u0k005U0670008J003Y003Y - private static readonly Color DarkBookmarkDefaultSystemColor = SystemColors.ControlDarkDark; // Important: only supports SystemColors - private static readonly Color LessLessDarkBackgroundColor = Color.FromArgb(90, 90, 90); - private static readonly Color LessDarkBackgroundColor = Color.FromArgb(67, 67, 67); - private static readonly Color DarkBackgroundColor = Color.FromArgb(45, 45, 45); - private static readonly Color DarkerBackgroundColor = Color.FromArgb(30, 30, 30); - private static readonly Color DarkForeColor = Color.FromArgb(255, 255, 255); + // Dark Theme + // https://paletton.com/#uid=15-0u0k005U0670008J003Y003Y + private static readonly Color DarkBookmarkDefaultSystemColor = SystemColors.ControlDarkDark; // Important: only supports SystemColors + private static readonly Color LessLessDarkBackgroundColor = Color.FromArgb(90, 90, 90); + private static readonly Color LessDarkBackgroundColor = Color.FromArgb(67, 67, 67); + private static readonly Color DarkBackgroundColor = Color.FromArgb(45, 45, 45); + private static readonly Color DarkerBackgroundColor = Color.FromArgb(30, 30, 30); + private static readonly Color DarkForeColor = Color.FromArgb(255, 255, 255); - // Default - public static Color BackgroundColor = BrightBackgroundColor; - public static Color DockBackgroundColor = BrighterBackgroundColor; - public static Color BookmarksDefaultBackgroundColor = BrightBookmarkDefaultSystemColor; - public static Color ForeColor = BrightForeColor; - public static Color MenuBackgroundColor = BrighterBackgroundColor; - public static Color HoverMenuBackgroundColor = LessBrightBackgroundColor; - public static Color ActiveTabColor = BrighterBackgroundColor; - public static Color InactiveTabColor = LessBrightBackgroundColor; - public static Color TabsBackgroundStripColor = LessBrightBackgroundColor; + // Default + public static Color BackgroundColor = BrightBackgroundColor; + public static Color DockBackgroundColor = BrighterBackgroundColor; + public static Color BookmarksDefaultBackgroundColor = BrightBookmarkDefaultSystemColor; + public static Color ForeColor = BrightForeColor; + public static Color MenuBackgroundColor = BrighterBackgroundColor; + public static Color HoverMenuBackgroundColor = LessBrightBackgroundColor; + public static Color ActiveTabColor = BrighterBackgroundColor; + public static Color InactiveTabColor = LessBrightBackgroundColor; + public static Color TabsBackgroundStripColor = LessBrightBackgroundColor; - public static bool DarkModeEnabled; + public static bool DarkModeEnabled; - public static void LoadColorMode(bool darkMode) + public static void LoadColorMode(bool darkMode) + { + if (darkMode) { - if (darkMode) - { - SetDarkMode(); - } - else - { - SetBrightMode(); - } + SetDarkMode(); } - - private static void SetDarkMode() + else { - BackgroundColor = DarkBackgroundColor; - ForeColor = DarkForeColor; - MenuBackgroundColor = DarkerBackgroundColor; - DockBackgroundColor = LessDarkBackgroundColor; - HoverMenuBackgroundColor = LessDarkBackgroundColor; - BookmarksDefaultBackgroundColor = DarkBookmarkDefaultSystemColor; - TabsBackgroundStripColor = LessDarkBackgroundColor; - ActiveTabColor = LessLessDarkBackgroundColor; - InactiveTabColor = LessDarkBackgroundColor; - DarkModeEnabled = true; + SetBrightMode(); } + } - private static void SetBrightMode() - { - BackgroundColor = BrightBackgroundColor; - ForeColor = BrightForeColor; - MenuBackgroundColor = BrighterBackgroundColor; - DockBackgroundColor = BrighterBackgroundColor; - BookmarksDefaultBackgroundColor = BrightBookmarkDefaultSystemColor; - HoverMenuBackgroundColor = LessBrightBackgroundColor; - TabsBackgroundStripColor = BrighterBackgroundColor; - ActiveTabColor = BrighterBackgroundColor; - InactiveTabColor = LessBrightBackgroundColor; - DarkModeEnabled = false; - } + private static void SetDarkMode() + { + BackgroundColor = DarkBackgroundColor; + ForeColor = DarkForeColor; + MenuBackgroundColor = DarkerBackgroundColor; + DockBackgroundColor = LessDarkBackgroundColor; + HoverMenuBackgroundColor = LessDarkBackgroundColor; + BookmarksDefaultBackgroundColor = DarkBookmarkDefaultSystemColor; + TabsBackgroundStripColor = LessDarkBackgroundColor; + ActiveTabColor = LessLessDarkBackgroundColor; + InactiveTabColor = LessDarkBackgroundColor; + DarkModeEnabled = true; + } + + private static void SetBrightMode() + { + BackgroundColor = BrightBackgroundColor; + ForeColor = BrightForeColor; + MenuBackgroundColor = BrighterBackgroundColor; + DockBackgroundColor = BrighterBackgroundColor; + BookmarksDefaultBackgroundColor = BrightBookmarkDefaultSystemColor; + HoverMenuBackgroundColor = LessBrightBackgroundColor; + TabsBackgroundStripColor = BrighterBackgroundColor; + ActiveTabColor = BrighterBackgroundColor; + InactiveTabColor = LessBrightBackgroundColor; + DarkModeEnabled = false; } } diff --git a/src/LogExpert.Core/Config/ColumnizerHistoryEntry.cs b/src/LogExpert.Core/Config/ColumnizerHistoryEntry.cs index 1320bba6..88948893 100644 --- a/src/LogExpert.Core/Config/ColumnizerHistoryEntry.cs +++ b/src/LogExpert.Core/Config/ColumnizerHistoryEntry.cs @@ -4,27 +4,26 @@ #endregion -namespace LogExpert.Core.Config +namespace LogExpert.Core.Config; + +[Serializable] +public class ColumnizerHistoryEntry { - [Serializable] - public class ColumnizerHistoryEntry - { - #region cTor + #region cTor - public ColumnizerHistoryEntry(string fileName, string columnizerName) - { - FileName = fileName; - ColumnizerName = columnizerName; - } + public ColumnizerHistoryEntry(string fileName, string columnizerName) + { + FileName = fileName; + ColumnizerName = columnizerName; + } - #endregion + #endregion - #region Fields + #region Fields - public string FileName { get; } + public string FileName { get; } - #endregion + #endregion - public string ColumnizerName { get; } - } + public string ColumnizerName { get; } } \ No newline at end of file diff --git a/src/LogExpert.Core/Config/ColumnizerMaskEntry.cs b/src/LogExpert.Core/Config/ColumnizerMaskEntry.cs index d15d0fc1..37586ec5 100644 --- a/src/LogExpert.Core/Config/ColumnizerMaskEntry.cs +++ b/src/LogExpert.Core/Config/ColumnizerMaskEntry.cs @@ -1,15 +1,14 @@ using System; -namespace LogExpert.Core.Config +namespace LogExpert.Core.Config; + +[Serializable] +public class ColumnizerMaskEntry { - [Serializable] - public class ColumnizerMaskEntry - { - #region Fields + #region Fields - public string columnizerName; - public string mask; + public string columnizerName; + public string mask; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Config/ExportImportFlags.cs b/src/LogExpert.Core/Config/ExportImportFlags.cs index 7eea55a7..1e3326e5 100644 --- a/src/LogExpert.Core/Config/ExportImportFlags.cs +++ b/src/LogExpert.Core/Config/ExportImportFlags.cs @@ -1,16 +1,15 @@ -namespace LogExpert.Core.Config +namespace LogExpert.Core.Config; + +[Flags] +public enum ExportImportFlags : long { - [Flags] - public enum ExportImportFlags : long - { - None = 0, - HighlightSettings = 1, - ColumnizerMasks = 2, - HighlightMasks = 4, - ToolEntries = 8, - Other = 16, - KeepExisting = 32, - All = HighlightSettings | ColumnizerMasks | HighlightMasks | ToolEntries | Other, - AllKeepExisting = All | KeepExisting - } + None = 0, + HighlightSettings = 1, + ColumnizerMasks = 2, + HighlightMasks = 4, + ToolEntries = 8, + Other = 16, + KeepExisting = 32, + All = HighlightSettings | ColumnizerMasks | HighlightMasks | ToolEntries | Other, + AllKeepExisting = All | KeepExisting } \ No newline at end of file diff --git a/src/LogExpert.Core/Config/HighlightMaskEntry.cs b/src/LogExpert.Core/Config/HighlightMaskEntry.cs index 7435222d..cf1f40d2 100644 --- a/src/LogExpert.Core/Config/HighlightMaskEntry.cs +++ b/src/LogExpert.Core/Config/HighlightMaskEntry.cs @@ -1,15 +1,14 @@ using System; -namespace LogExpert.Core.Config +namespace LogExpert.Core.Config; + +[Serializable] +public class HighlightMaskEntry { - [Serializable] - public class HighlightMaskEntry - { - #region Fields + #region Fields - public string highlightGroupName; - public string mask; + public string highlightGroupName; + public string mask; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Config/MultiFileOption.cs b/src/LogExpert.Core/Config/MultiFileOption.cs index 5dbb3ab8..7dce5106 100644 --- a/src/LogExpert.Core/Config/MultiFileOption.cs +++ b/src/LogExpert.Core/Config/MultiFileOption.cs @@ -1,12 +1,11 @@ using System; -namespace LogExpert.Core.Config +namespace LogExpert.Core.Config; + +[Serializable] +public enum MultiFileOption { - [Serializable] - public enum MultiFileOption - { - SingleFiles, - MultiFile, - Ask - } + SingleFiles, + MultiFile, + Ask } \ No newline at end of file diff --git a/src/LogExpert.Core/Config/Preferences.cs b/src/LogExpert.Core/Config/Preferences.cs index a757b1bb..333465ec 100644 --- a/src/LogExpert.Core/Config/Preferences.cs +++ b/src/LogExpert.Core/Config/Preferences.cs @@ -3,110 +3,109 @@ using System.Drawing; -namespace LogExpert.Core.Config +namespace LogExpert.Core.Config; + +[Serializable] +public class Preferences { - [Serializable] - public class Preferences - { - #region Fields + #region Fields - public bool allowOnlyOneInstance; + public bool allowOnlyOneInstance; - public bool askForClose = false; + public bool askForClose; - public bool darkMode = false; + public bool darkMode; - public int bufferCount = 100; + public int bufferCount = 100; - public List columnizerMaskList = []; + public List columnizerMaskList = []; - public string defaultEncoding; + public string defaultEncoding; - public bool filterSync = true; + public bool filterSync = true; - public bool filterTail = true; + public bool filterTail = true; - public bool followTail = true; + public bool followTail = true; - public string fontName = "Courier New"; + public string fontName = "Courier New"; - public float fontSize = 9; + public float fontSize = 9; - public List highlightMaskList = []; + public List highlightMaskList = []; - public List HighlightGroupList { get; set; } = []; + public List HighlightGroupList { get; set; } = []; - public bool isAutoHideFilterList = false; + public bool isAutoHideFilterList; - public bool isFilterOnLoad; + public bool isFilterOnLoad; - public int lastColumnWidth = 2000; + public int lastColumnWidth = 2000; - public int linesPerBuffer = 500; + public int linesPerBuffer = 500; - public int maximumFilterEntries = 30; + public int maximumFilterEntries = 30; - public int maximumFilterEntriesDisplayed = 20; + public int maximumFilterEntriesDisplayed = 20; - public bool maskPrio; + public bool maskPrio; - public bool autoPick; + public bool autoPick; - //Refactor Enum - public MultiFileOption multiFileOption; + //Refactor Enum + public MultiFileOption multiFileOption; - //Refactor class? - public MultiFileOptions multiFileOptions; + //Refactor class? + public MultiFileOptions multiFileOptions; - public bool multiThreadFilter = true; + public bool multiThreadFilter = true; - public bool openLastFiles = true; + public bool openLastFiles = true; - public int pollingInterval = 250; + public int pollingInterval = 250; - public bool reverseAlpha = false; + public bool reverseAlpha; - public bool PortableMode { get; set; } + public bool PortableMode { get; set; } - /// - /// Save Directory of the last logfile - /// - public string sessionSaveDirectory = null; + /// + /// Save Directory of the last logfile + /// + public string sessionSaveDirectory; - public bool saveFilters = true; + public bool saveFilters = true; - public SessionSaveLocation saveLocation = SessionSaveLocation.DocumentsDir; + public SessionSaveLocation saveLocation = SessionSaveLocation.DocumentsDir; - public bool saveSessions = true; + public bool saveSessions = true; - public bool setLastColumnWidth; + public bool setLastColumnWidth; - public bool showBubbles = true; + public bool showBubbles = true; - public bool showColumnFinder; + public bool showColumnFinder; - public Color showTailColor = Color.FromKnownColor(KnownColor.Blue); + public Color showTailColor = Color.FromKnownColor(KnownColor.Blue); - public bool showTailState = true; + public bool showTailState = true; - public bool showTimeSpread = false; + public bool showTimeSpread; - public Color timeSpreadColor = Color.FromKnownColor(KnownColor.Gray); + public Color timeSpreadColor = Color.FromKnownColor(KnownColor.Gray); - public bool timeSpreadTimeMode; + public bool timeSpreadTimeMode; - public bool timestampControl = true; + public bool timestampControl = true; - public DragOrientationsEnum timestampControlDragOrientation = DragOrientationsEnum.Horizontal; + public DragOrientationsEnum timestampControlDragOrientation = DragOrientationsEnum.Horizontal; - public List toolEntries = []; + public List toolEntries = []; - public bool useLegacyReader; + public bool useLegacyReader; - public bool ShowErrorMessageAllowOnlyOneInstances { get; set; } + public bool ShowErrorMessageAllowOnlyOneInstances { get; set; } - public int MaxLineLength { get; set; } = 20000; + public int MaxLineLength { get; set; } = 20000; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Config/RegexHistory.cs b/src/LogExpert.Core/Config/RegexHistory.cs index a00fd630..994b21b5 100644 --- a/src/LogExpert.Core/Config/RegexHistory.cs +++ b/src/LogExpert.Core/Config/RegexHistory.cs @@ -1,13 +1,12 @@ using System; using System.Collections.Generic; -namespace LogExpert.Core.Config +namespace LogExpert.Core.Config; + +[Serializable] +public class RegexHistory { - [Serializable] - public class RegexHistory - { - public List ExpressionHistoryList { get; set; } = []; + public List ExpressionHistoryList { get; set; } = []; - public List TesttextHistoryList { get; set; } = []; - } + public List TesttextHistoryList { get; set; } = []; } \ No newline at end of file diff --git a/src/LogExpert.Core/Config/SessionSaveLocation.cs b/src/LogExpert.Core/Config/SessionSaveLocation.cs index 2b9b6ce8..7e559d6c 100644 --- a/src/LogExpert.Core/Config/SessionSaveLocation.cs +++ b/src/LogExpert.Core/Config/SessionSaveLocation.cs @@ -1,26 +1,25 @@ using System; -namespace LogExpert.Core.Config +namespace LogExpert.Core.Config; + +[Serializable] +public enum SessionSaveLocation { - [Serializable] - public enum SessionSaveLocation - { - //Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + Path.DirectorySeparatorChar + "LogExpert" - /// - /// - /// - DocumentsDir, - //same directory as the logfile - SameDir, - //uses configured folder to save the session files - /// - /// - /// - OwnDir, - /// - /// - /// - ApplicationStartupDir, - LoadedSessionFile - } + //Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + Path.DirectorySeparatorChar + "LogExpert" + /// + /// + /// + DocumentsDir, + //same directory as the logfile + SameDir, + //uses configured folder to save the session files + /// + /// + /// + OwnDir, + /// + /// + /// + ApplicationStartupDir, + LoadedSessionFile } \ No newline at end of file diff --git a/src/LogExpert.Core/Config/Settings.cs b/src/LogExpert.Core/Config/Settings.cs index 275bd2c1..461ec6d9 100644 --- a/src/LogExpert.Core/Config/Settings.cs +++ b/src/LogExpert.Core/Config/Settings.cs @@ -1,55 +1,54 @@ +using System.Drawing; + using LogExpert.Core.Classes.Filter; using LogExpert.Core.Entities; -using System.Drawing; +namespace LogExpert.Core.Config; -namespace LogExpert.Core.Config +[Serializable] +public class Settings { - [Serializable] - public class Settings - { - #region Fields + #region Fields - public bool alwaysOnTop; + public bool alwaysOnTop; - public Rectangle appBounds; + public Rectangle appBounds; - public Rectangle appBoundsFullscreen; + public Rectangle appBoundsFullscreen; - public IList columnizerHistoryList = []; + public IList columnizerHistoryList = []; - public List fileColors = []; + public List fileColors = []; - public List fileHistoryList = []; + public List fileHistoryList = []; - public List filterHistoryList = []; + public List filterHistoryList = []; - public List filterList = []; + public List filterList = []; - public FilterParams filterParams = new(); + public FilterParams filterParams = new(); - public List filterRangeHistoryList = []; + public List filterRangeHistoryList = []; - public bool hideLineColumn; + public bool hideLineColumn; - public bool isMaximized; + public bool isMaximized; - public string lastDirectory; + public string lastDirectory; - public List lastOpenFilesList = []; + public List lastOpenFilesList = []; - public Preferences Preferences { get; set; } = new(); + public Preferences Preferences { get; set; } = new(); - public RegexHistory RegexHistory { get; set; } = new(); + public RegexHistory RegexHistory { get; set; } = new(); - public List searchHistoryList = []; + public List searchHistoryList = []; - public SearchParams searchParams = new(); + public SearchParams searchParams = new(); - public IList uriHistoryList = []; + public IList uriHistoryList = []; - public int versionBuild; + public int versionBuild; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Config/SettingsFlags.cs b/src/LogExpert.Core/Config/SettingsFlags.cs index 303874da..36299106 100644 --- a/src/LogExpert.Core/Config/SettingsFlags.cs +++ b/src/LogExpert.Core/Config/SettingsFlags.cs @@ -1,24 +1,23 @@ using System; -namespace LogExpert.Core.Config +namespace LogExpert.Core.Config; + +[Flags] +public enum SettingsFlags : long { - [Flags] - public enum SettingsFlags : long - { - None = 0, - WindowPosition = 1, - FileHistory = 2, - HighlightSettings = 4, - FilterList = 8, - RegexHistory = 16, - ToolSettings = 32, - GuiOrColors = 64, - FilterHistory = 128, + None = 0, + WindowPosition = 1, + FileHistory = 2, + HighlightSettings = 4, + FilterList = 8, + RegexHistory = 16, + ToolSettings = 32, + GuiOrColors = 64, + FilterHistory = 128, - All = WindowPosition | FileHistory | HighlightSettings | - FilterList | RegexHistory | ToolSettings | GuiOrColors | - FilterHistory, + All = WindowPosition | FileHistory | HighlightSettings | + FilterList | RegexHistory | ToolSettings | GuiOrColors | + FilterHistory, - Settings = All & ~WindowPosition & ~FileHistory, - } + Settings = All & ~WindowPosition & ~FileHistory, } \ No newline at end of file diff --git a/src/LogExpert.Core/Config/ToolEntry.cs b/src/LogExpert.Core/Config/ToolEntry.cs index 137eef32..bb5d4d1e 100644 --- a/src/LogExpert.Core/Config/ToolEntry.cs +++ b/src/LogExpert.Core/Config/ToolEntry.cs @@ -2,47 +2,46 @@ using LogExpert.Core.Classes; -namespace LogExpert.Core.Config +namespace LogExpert.Core.Config; + +[Serializable] +public class ToolEntry { - [Serializable] - public class ToolEntry + #region Fields + + public string args = ""; + public string cmd = ""; + public string columnizerName = ""; + public string iconFile; + public int iconIndex; + public bool isFavourite; + public string name; + public bool sysout; + public string workingDir = ""; + + #endregion + + #region Public methods + + public override string ToString() { - #region Fields - - public string args = ""; - public string cmd = ""; - public string columnizerName = ""; - public string iconFile; - public int iconIndex; - public bool isFavourite; - public string name; - public bool sysout = false; - public string workingDir = ""; - - #endregion - - #region Public methods - - public override string ToString() - { - return Util.IsNull(name) ? cmd : name; - } - - public ToolEntry Clone() - { - ToolEntry clone = new(); - clone.cmd = cmd; - clone.args = args; - clone.name = name; - clone.sysout = sysout; - clone.columnizerName = columnizerName; - clone.isFavourite = isFavourite; - clone.iconFile = iconFile; - clone.iconIndex = iconIndex; - clone.workingDir = workingDir; - return clone; - } - - #endregion + return Util.IsNull(name) ? cmd : name; } + + public ToolEntry Clone() + { + ToolEntry clone = new(); + clone.cmd = cmd; + clone.args = args; + clone.name = name; + clone.sysout = sysout; + clone.columnizerName = columnizerName; + clone.isFavourite = isFavourite; + clone.iconFile = iconFile; + clone.iconIndex = iconIndex; + clone.workingDir = workingDir; + return clone; + } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Entities/Bookmark.cs b/src/LogExpert.Core/Entities/Bookmark.cs index a150b8f3..4ebb1e80 100644 --- a/src/LogExpert.Core/Entities/Bookmark.cs +++ b/src/LogExpert.Core/Entities/Bookmark.cs @@ -1,40 +1,39 @@ using System.Drawing; -namespace LogExpert.Core.Entities +namespace LogExpert.Core.Entities; + +public class Bookmark { - public class Bookmark - { - #region cTor + #region cTor - public Bookmark(int lineNum) - { - LineNum = lineNum; - Text = string.Empty; - Overlay = new BookmarkOverlay(); - } + public Bookmark(int lineNum) + { + LineNum = lineNum; + Text = string.Empty; + Overlay = new BookmarkOverlay(); + } - public Bookmark(int lineNum, string comment) - { - LineNum = lineNum; - Text = comment; - Overlay = new BookmarkOverlay(); - } + public Bookmark(int lineNum, string comment) + { + LineNum = lineNum; + Text = comment; + Overlay = new BookmarkOverlay(); + } - #endregion + #endregion - #region Properties + #region Properties - public int LineNum { get; set; } + public int LineNum { get; set; } - public string Text { get; set; } + public string Text { get; set; } - public BookmarkOverlay Overlay { get; set; } + public BookmarkOverlay Overlay { get; set; } - /// - /// Position offset of the overlay as set by the user by dragging the overlay with the mouse. - /// - public Size OverlayOffset { get; set; } + /// + /// Position offset of the overlay as set by the user by dragging the overlay with the mouse. + /// + public Size OverlayOffset { get; set; } - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Entities/BookmarkCollection.cs b/src/LogExpert.Core/Entities/BookmarkCollection.cs index a5d48b8a..0cc0917c 100644 --- a/src/LogExpert.Core/Entities/BookmarkCollection.cs +++ b/src/LogExpert.Core/Entities/BookmarkCollection.cs @@ -1,23 +1,22 @@ using System.Collections.ObjectModel; -namespace LogExpert.Core.Entities -{ - public class BookmarkCollection : ReadOnlyCollection - { - #region Fields +namespace LogExpert.Core.Entities; - private SortedList bookmarkList; +public class BookmarkCollection : ReadOnlyCollection +{ + #region Fields - #endregion + private SortedList bookmarkList; - #region cTor + #endregion - internal BookmarkCollection(SortedList bookmarkList) - : base(bookmarkList.Values) - { - this.bookmarkList = bookmarkList; - } + #region cTor - #endregion + internal BookmarkCollection(SortedList bookmarkList) + : base(bookmarkList.Values) + { + this.bookmarkList = bookmarkList; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Entities/BookmarkOverlay.cs b/src/LogExpert.Core/Entities/BookmarkOverlay.cs index b4ccff75..805ee15d 100644 --- a/src/LogExpert.Core/Entities/BookmarkOverlay.cs +++ b/src/LogExpert.Core/Entities/BookmarkOverlay.cs @@ -1,17 +1,16 @@ using System.Drawing; -namespace LogExpert.Core.Entities +namespace LogExpert.Core.Entities; + +public class BookmarkOverlay { - public class BookmarkOverlay - { - #region Properties + #region Properties - public Bookmark Bookmark { get; set; } + public Bookmark Bookmark { get; set; } - public Point Position { get; set; } + public Point Position { get; set; } - public Rectangle BubbleRect { get; set; } + public Rectangle BubbleRect { get; set; } - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Entities/DebugOptions.cs b/src/LogExpert.Core/Entities/DebugOptions.cs index 10f0b768..f6e1fcfd 100644 --- a/src/LogExpert.Core/Entities/DebugOptions.cs +++ b/src/LogExpert.Core/Entities/DebugOptions.cs @@ -1,7 +1,6 @@ -namespace LogExpert.Core.Entities +namespace LogExpert.Core.Entities; + +public class DebugOptions { - public class DebugOptions - { - public static bool DisableWordHighlight { get; set; } = false; - } + public static bool DisableWordHighlight { get; set; } } \ No newline at end of file diff --git a/src/LogExpert.Core/Entities/DefaultLogfileColumnizer.cs b/src/LogExpert.Core/Entities/DefaultLogfileColumnizer.cs index 9f1a327e..ab955862 100644 --- a/src/LogExpert.Core/Entities/DefaultLogfileColumnizer.cs +++ b/src/LogExpert.Core/Entities/DefaultLogfileColumnizer.cs @@ -1,86 +1,82 @@ -namespace LogExpert.Core.Entities +namespace LogExpert.Core.Entities; + +public class DefaultLogfileColumnizer : ILogLineColumnizer { - public class DefaultLogfileColumnizer : ILogLineColumnizer + #region ILogLineColumnizer Members + + public string GetName() { - #region ILogLineColumnizer Members + return "Default (single line)"; + } - public string GetName() - { - return "Default (single line)"; - } + public string GetDescription() + { + return "No column splitting. The whole line is displayed in a single column."; + } - public string GetDescription() - { - return "No column splitting. The whole line is displayed in a single column."; - } + public int GetColumnCount() + { + return 1; + } - public int GetColumnCount() - { - return 1; - } + public string[] GetColumnNames() + { + return ["Text"]; + } - public string[] GetColumnNames() + public IColumnizedLogLine SplitLine(ILogLineColumnizerCallback callback, ILogLine line) + { + ColumnizedLogLine cLogLine = new() { - return ["Text"]; - } + LogLine = line + }; - public IColumnizedLogLine SplitLine(ILogLineColumnizerCallback callback, ILogLine line) - { - ColumnizedLogLine cLogLine = new() + cLogLine.ColumnValues = + [ + new Column { - LogLine = line - }; + FullValue = line.FullLine, + Parent = cLogLine + } + ]; - cLogLine.ColumnValues = - [ - new Column - { - FullValue = line.FullLine, - Parent = cLogLine - } - ]; + return cLogLine; + } - return cLogLine; - } - - public string Text - { - get { return GetName(); } - } - - public Priority GetPriority(string fileName, IEnumerable samples) - { - return Priority.CanSupport; - } - #endregion + public string Text => GetName(); - #region ILogLineColumnizer Not implemented Members + public Priority GetPriority(string fileName, IEnumerable samples) + { + return Priority.CanSupport; + } + #endregion - public bool IsTimeshiftImplemented() - { - return false; - } + #region ILogLineColumnizer Not implemented Members - public void SetTimeOffset(int msecOffset) - { - throw new NotImplementedException(); - } + public bool IsTimeshiftImplemented() + { + return false; + } - public int GetTimeOffset() - { - throw new NotImplementedException(); - } + public void SetTimeOffset(int msecOffset) + { + throw new NotImplementedException(); + } - public DateTime GetTimestamp(ILogLineColumnizerCallback callback, ILogLine line) - { - throw new NotImplementedException(); - } + public int GetTimeOffset() + { + throw new NotImplementedException(); + } - public void PushValue(ILogLineColumnizerCallback callback, int column, string value, string oldValue) - { - } + public DateTime GetTimestamp(ILogLineColumnizerCallback callback, ILogLine line) + { + throw new NotImplementedException(); + } - #endregion + public void PushValue(ILogLineColumnizerCallback callback, int column, string value, string oldValue) + { } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Entities/EncodingOptions.cs b/src/LogExpert.Core/Entities/EncodingOptions.cs index d66bd336..dae7e680 100644 --- a/src/LogExpert.Core/Entities/EncodingOptions.cs +++ b/src/LogExpert.Core/Entities/EncodingOptions.cs @@ -1,24 +1,23 @@ using System.Text; -namespace LogExpert.Core.Entities +namespace LogExpert.Core.Entities; + +/// +/// Holds some encoding options. +/// +public class EncodingOptions { + #region Properties + /// - /// Holds some encoding options. + /// Sets or gets the Encoding which shall be used when reading a file. A value of null means 'please autodetect' via BOM. /// - public class EncodingOptions - { - #region Properties - - /// - /// Sets or gets the Encoding which shall be used when reading a file. A value of null means 'please autodetect' via BOM. - /// - public Encoding Encoding { get; set; } + public Encoding Encoding { get; set; } - /// - /// The Encoding to be used when autodetect cannot be applied (missing BOM). Only used when Encoding is set to null. - /// - public Encoding DefaultEncoding { get; set; } + /// + /// The Encoding to be used when autodetect cannot be applied (missing BOM). Only used when Encoding is set to null. + /// + public Encoding DefaultEncoding { get; set; } - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Entities/FileViewContext.cs b/src/LogExpert.Core/Entities/FileViewContext.cs index efcc7577..8cc0a27a 100644 --- a/src/LogExpert.Core/Entities/FileViewContext.cs +++ b/src/LogExpert.Core/Entities/FileViewContext.cs @@ -1,15 +1,14 @@ using LogExpert.Core.Interface; -namespace LogExpert.Core.Entities +namespace LogExpert.Core.Entities; + +public class FileViewContext(ILogPaintContext logPaintContext, ILogView logView) : IFileViewContext, ILogPaintContext { - public class FileViewContext(ILogPaintContext logPaintContext, ILogView logView) : IFileViewContext, ILogPaintContext - { - #region Properties + #region Properties - public ILogPaintContext LogPaintContext { get; } = logPaintContext; + public ILogPaintContext LogPaintContext { get; } = logPaintContext; - public ILogView LogView { get; } = logView; + public ILogView LogView { get; } = logView; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Entities/HighlightGroup.cs b/src/LogExpert.Core/Entities/HighlightGroup.cs index 1ce4471b..a599d198 100644 --- a/src/LogExpert.Core/Entities/HighlightGroup.cs +++ b/src/LogExpert.Core/Entities/HighlightGroup.cs @@ -1,31 +1,30 @@ using LogExpert.Core.Classes.Highlight; -namespace LogExpert.Core.Entities +namespace LogExpert.Core.Entities; + +[Serializable] +public class HighlightGroup : ICloneable { - [Serializable] - public class HighlightGroup : ICloneable - { - #region Properties + #region Properties - public string GroupName { get; set; } = string.Empty; + public string GroupName { get; set; } = string.Empty; - public List HighlightEntryList { get; set; } = []; + public List HighlightEntryList { get; set; } = []; - public object Clone() + public object Clone() + { + HighlightGroup clone = new() { - HighlightGroup clone = new() - { - GroupName = GroupName - }; + GroupName = GroupName + }; - foreach (HighlightEntry entry in HighlightEntryList) - { - clone.HighlightEntryList.Add((HighlightEntry)entry.Clone()); - } - - return clone; + foreach (HighlightEntry entry in HighlightEntryList) + { + clone.HighlightEntryList.Add((HighlightEntry)entry.Clone()); } - #endregion + return clone; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Entities/LogEventData.cs b/src/LogExpert.Core/Entities/LogEventData.cs index 923b47ab..70b368b5 100644 --- a/src/LogExpert.Core/Entities/LogEventData.cs +++ b/src/LogExpert.Core/Entities/LogEventData.cs @@ -1,25 +1,24 @@ -namespace LogExpert.Core.Entities +namespace LogExpert.Core.Entities; + +public class LogEventArgs : System.EventArgs { - public class LogEventArgs : System.EventArgs - { - #region Fields + #region Fields - #endregion + #endregion - #region Properties + #region Properties - public int RolloverOffset { get; set; } = 0; + public int RolloverOffset { get; set; } - public bool IsRollover { get; set; } = false; + public bool IsRollover { get; set; } - public long FileSize { get; set; } + public long FileSize { get; set; } - public int LineCount { get; set; } + public int LineCount { get; set; } - public int PrevLineCount { get; set; } + public int PrevLineCount { get; set; } - public long PrevFileSize { get; set; } + public long PrevFileSize { get; set; } - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Entities/LogFileException.cs b/src/LogExpert.Core/Entities/LogFileException.cs index 3368e8c3..08384374 100644 --- a/src/LogExpert.Core/Entities/LogFileException.cs +++ b/src/LogExpert.Core/Entities/LogFileException.cs @@ -1,19 +1,22 @@ -namespace LogExpert.Core.Entities +namespace LogExpert.Core.Entities; + +public class LogFileException : Exception { - public class LogFileException : ApplicationException - { - #region cTor + #region cTor - public LogFileException(string msg) - : base(msg) - { - } + public LogFileException (string msg) + : base(msg) + { + } - public LogFileException(string msg, Exception inner) - : base(msg, inner) - { - } + public LogFileException (string msg, Exception inner) + : base(msg, inner) + { + } - #endregion + public LogFileException () + { } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Entities/MultifileOptions.cs b/src/LogExpert.Core/Entities/MultifileOptions.cs index 04858e4e..b9ab6d78 100644 --- a/src/LogExpert.Core/Entities/MultifileOptions.cs +++ b/src/LogExpert.Core/Entities/MultifileOptions.cs @@ -1,14 +1,13 @@ -namespace LogExpert.Core.Entities +namespace LogExpert.Core.Entities; + +[Serializable] +public class MultiFileOptions { - [Serializable] - public class MultiFileOptions - { - #region Properties + #region Properties - public int MaxDayTry { get; set; } = 3; + public int MaxDayTry { get; set; } = 3; - public string FormatPattern { get; set; } = "*$J(.)"; + public string FormatPattern { get; set; } = "*$J(.)"; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Entities/Range.cs b/src/LogExpert.Core/Entities/Range.cs index c2c9f1b3..e9d40540 100644 --- a/src/LogExpert.Core/Entities/Range.cs +++ b/src/LogExpert.Core/Entities/Range.cs @@ -1,31 +1,30 @@ -namespace LogExpert.Core.Entities +namespace LogExpert.Core.Entities; + +public class Range { - public class Range - { - #region Fields + #region Fields - #endregion + #endregion - #region cTor + #region cTor - public Range() - { - } + public Range() + { + } - public Range(int startLine, int endLine) - { - StartLine = startLine; - EndLine = endLine; - } + public Range(int startLine, int endLine) + { + StartLine = startLine; + EndLine = endLine; + } - #endregion + #endregion - #region Properties + #region Properties - public int StartLine { get; set; } + public int StartLine { get; set; } - public int EndLine { get; set; } + public int EndLine { get; set; } - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Entities/ReloadMemento.cs b/src/LogExpert.Core/Entities/ReloadMemento.cs index 03f9cfa9..bbb82015 100644 --- a/src/LogExpert.Core/Entities/ReloadMemento.cs +++ b/src/LogExpert.Core/Entities/ReloadMemento.cs @@ -1,9 +1,8 @@ -namespace LogExpert.Core.Entities +namespace LogExpert.Core.Entities; + +public class ReloadMemento { - public class ReloadMemento - { - public int CurrentLine { get; set; } + public int CurrentLine { get; set; } - public int FirstDisplayedLine { get; set; } - } + public int FirstDisplayedLine { get; set; } } \ No newline at end of file diff --git a/src/LogExpert.Core/Entities/RowHeightEntry.cs b/src/LogExpert.Core/Entities/RowHeightEntry.cs index 26c879a2..00c79bc7 100644 --- a/src/LogExpert.Core/Entities/RowHeightEntry.cs +++ b/src/LogExpert.Core/Entities/RowHeightEntry.cs @@ -1,29 +1,28 @@ -namespace LogExpert.Core.Entities +namespace LogExpert.Core.Entities; + +public class RowHeightEntry { - public class RowHeightEntry - { - #region cTor + #region cTor - public RowHeightEntry() - { - LineNum = 0; - Height = 0; - } + public RowHeightEntry() + { + LineNum = 0; + Height = 0; + } - public RowHeightEntry(int lineNum, int height) - { - LineNum = lineNum; - Height = height; - } + public RowHeightEntry(int lineNum, int height) + { + LineNum = lineNum; + Height = height; + } - #endregion + #endregion - #region Properties + #region Properties - public int LineNum { get; set; } + public int LineNum { get; set; } - public int Height { get; set; } + public int Height { get; set; } - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Entities/SearchParams.cs b/src/LogExpert.Core/Entities/SearchParams.cs index a3e8e75f..ed4b2748 100644 --- a/src/LogExpert.Core/Entities/SearchParams.cs +++ b/src/LogExpert.Core/Entities/SearchParams.cs @@ -1,25 +1,24 @@ -namespace LogExpert.Core.Entities +namespace LogExpert.Core.Entities; + +[Serializable] +public class SearchParams { - [Serializable] - public class SearchParams - { - public int CurrentLine { get; set; } + public int CurrentLine { get; set; } - public List HistoryList { get; set; } = []; + public List HistoryList { get; set; } = []; - public bool IsCaseSensitive { get; set; } = false; + public bool IsCaseSensitive { get; set; } - public bool IsFindNext { get; set; } + public bool IsFindNext { get; set; } - public bool IsForward { get; set; } = true; + public bool IsForward { get; set; } = true; - public bool IsFromTop { get; set; } = false; + public bool IsFromTop { get; set; } - public bool IsRegex { get; set; } = false; + public bool IsRegex { get; set; } - public string SearchText { get; set; } = string.Empty; + public string SearchText { get; set; } = string.Empty; - [field: NonSerialized] - public bool IsShiftF3Pressed { get; set; } - } + [field: NonSerialized] + public bool IsShiftF3Pressed { get; set; } } \ No newline at end of file diff --git a/src/LogExpert.Core/Enums/DragOrientationsEnum.cs b/src/LogExpert.Core/Enums/DragOrientationsEnum.cs index ccb32aa5..fb6465c4 100644 --- a/src/LogExpert.Core/Enums/DragOrientationsEnum.cs +++ b/src/LogExpert.Core/Enums/DragOrientationsEnum.cs @@ -1,9 +1,8 @@ -namespace LogExpert.Core.Enums +namespace LogExpert.Core.Enums; + +public enum DragOrientationsEnum { - public enum DragOrientationsEnum - { - Horizontal, - Vertical, - InvertedVertical - } + Horizontal, + Vertical, + InvertedVertical } diff --git a/src/LogExpert.Core/Enums/ProjectLoadDlgResult.cs b/src/LogExpert.Core/Enums/ProjectLoadDlgResult.cs index aa1f648b..c32b6c2c 100644 --- a/src/LogExpert.Core/Enums/ProjectLoadDlgResult.cs +++ b/src/LogExpert.Core/Enums/ProjectLoadDlgResult.cs @@ -1,10 +1,9 @@ -namespace LogExpert.Core.Enums +namespace LogExpert.Core.Enums; + +public enum ProjectLoadDlgResult { - public enum ProjectLoadDlgResult - { - Cancel, - CloseTabs, - NewWindow, - IgnoreLayout - } + Cancel, + CloseTabs, + NewWindow, + IgnoreLayout } \ No newline at end of file diff --git a/src/LogExpert.Core/Enums/WindowTypes.cs b/src/LogExpert.Core/Enums/WindowTypes.cs index f9ee40b2..6a726c9c 100644 --- a/src/LogExpert.Core/Enums/WindowTypes.cs +++ b/src/LogExpert.Core/Enums/WindowTypes.cs @@ -1,8 +1,7 @@ -namespace LogExpert.Core.Enums +namespace LogExpert.Core.Enums; + +public enum WindowTypes { - public enum WindowTypes - { - BookmarkWindow, - LogWindow, - } + BookmarkWindow, + LogWindow, } \ No newline at end of file diff --git a/src/LogExpert.Core/EventArguments/BookmarkEventArgs.cs b/src/LogExpert.Core/EventArguments/BookmarkEventArgs.cs index 2a600219..869b34be 100644 --- a/src/LogExpert.Core/EventArguments/BookmarkEventArgs.cs +++ b/src/LogExpert.Core/EventArguments/BookmarkEventArgs.cs @@ -1,13 +1,12 @@ using LogExpert.Core.Entities; -namespace LogExpert.Core.EventArguments +namespace LogExpert.Core.EventArguments; + +public class BookmarkEventArgs(Bookmark bookmark) : System.EventArgs { - public class BookmarkEventArgs(Bookmark bookmark) : System.EventArgs - { - #region Properties + #region Properties - public Bookmark Bookmark { get; } = bookmark; + public Bookmark Bookmark { get; } = bookmark; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/EventArguments/ColumnizerEventArgs.cs b/src/LogExpert.Core/EventArguments/ColumnizerEventArgs.cs index ad8ef92a..9e8bb006 100644 --- a/src/LogExpert.Core/EventArguments/ColumnizerEventArgs.cs +++ b/src/LogExpert.Core/EventArguments/ColumnizerEventArgs.cs @@ -1,11 +1,10 @@ -namespace LogExpert.Core.EventArguments +namespace LogExpert.Core.EventArguments; + +public class ColumnizerEventArgs(ILogLineColumnizer columnizer) : System.EventArgs { - public class ColumnizerEventArgs(ILogLineColumnizer columnizer) : System.EventArgs - { - #region Properties + #region Properties - public ILogLineColumnizer Columnizer { get; } = columnizer; + public ILogLineColumnizer Columnizer { get; } = columnizer; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/EventArguments/ConfigChangedEventArgs.cs b/src/LogExpert.Core/EventArguments/ConfigChangedEventArgs.cs index 243faa0d..c931dccf 100644 --- a/src/LogExpert.Core/EventArguments/ConfigChangedEventArgs.cs +++ b/src/LogExpert.Core/EventArguments/ConfigChangedEventArgs.cs @@ -1,13 +1,12 @@ using LogExpert.Core.Config; -namespace LogExpert.Core.EventArguments +namespace LogExpert.Core.EventArguments; + +public class ConfigChangedEventArgs(SettingsFlags changeFlags) : System.EventArgs { - public class ConfigChangedEventArgs(SettingsFlags changeFlags) : System.EventArgs - { - #region Properties + #region Properties - public SettingsFlags Flags { get; } = changeFlags; + public SettingsFlags Flags { get; } = changeFlags; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/EventArguments/ContextMenuPluginEventArgs.cs b/src/LogExpert.Core/EventArguments/ContextMenuPluginEventArgs.cs index 28df85f7..76d129cc 100644 --- a/src/LogExpert.Core/EventArguments/ContextMenuPluginEventArgs.cs +++ b/src/LogExpert.Core/EventArguments/ContextMenuPluginEventArgs.cs @@ -1,19 +1,18 @@ -namespace LogExpert.Core.EventArguments +namespace LogExpert.Core.EventArguments; + +public class ContextMenuPluginEventArgs(IContextMenuEntry entry, IList logLines, ILogLineColumnizer columnizer, + ILogExpertCallback callback) : System.EventArgs { - public class ContextMenuPluginEventArgs(IContextMenuEntry entry, IList logLines, ILogLineColumnizer columnizer, - ILogExpertCallback callback) : System.EventArgs - { - #region Properties + #region Properties - public IContextMenuEntry Entry { get; } = entry; + public IContextMenuEntry Entry { get; } = entry; - public IList LogLines { get; } = logLines; + public IList LogLines { get; } = logLines; - public ILogLineColumnizer Columnizer { get; } = columnizer; + public ILogLineColumnizer Columnizer { get; } = columnizer; - public ILogExpertCallback Callback { get; } = callback; + public ILogExpertCallback Callback { get; } = callback; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/EventArguments/CurrentHighlightGroupChangedEventArgs.cs b/src/LogExpert.Core/EventArguments/CurrentHighlightGroupChangedEventArgs.cs index efc33f45..7633e06c 100644 --- a/src/LogExpert.Core/EventArguments/CurrentHighlightGroupChangedEventArgs.cs +++ b/src/LogExpert.Core/EventArguments/CurrentHighlightGroupChangedEventArgs.cs @@ -1,16 +1,15 @@ using LogExpert.Core.Entities; using LogExpert.Core.Interface; -namespace LogExpert.Core.EventArguments +namespace LogExpert.Core.EventArguments; + +public class CurrentHighlightGroupChangedEventArgs(ILogWindow logWindow, HighlightGroup currentGroup) { - public class CurrentHighlightGroupChangedEventArgs(ILogWindow logWindow, HighlightGroup currentGroup) - { - #region Properties + #region Properties - public ILogWindow LogWindow { get; } = logWindow; + public ILogWindow LogWindow { get; } = logWindow; - public HighlightGroup CurrentGroup { get; } = currentGroup; + public HighlightGroup CurrentGroup { get; } = currentGroup; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/EventArguments/FilterListChangedEventArgs.cs b/src/LogExpert.Core/EventArguments/FilterListChangedEventArgs.cs index 684f993c..610bf8f3 100644 --- a/src/LogExpert.Core/EventArguments/FilterListChangedEventArgs.cs +++ b/src/LogExpert.Core/EventArguments/FilterListChangedEventArgs.cs @@ -1,14 +1,13 @@  using LogExpert.Core.Interface; -namespace LogExpert.Core.EventArguments +namespace LogExpert.Core.EventArguments; + +public class FilterListChangedEventArgs(ILogWindow logWindow) { - public class FilterListChangedEventArgs(ILogWindow logWindow) - { - #region Properties + #region Properties - public ILogWindow LogWindow { get; } = logWindow; + public ILogWindow LogWindow { get; } = logWindow; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/EventArguments/GuiStateArgs.cs b/src/LogExpert.Core/EventArguments/GuiStateArgs.cs index 25faf023..82ccc963 100644 --- a/src/LogExpert.Core/EventArguments/GuiStateArgs.cs +++ b/src/LogExpert.Core/EventArguments/GuiStateArgs.cs @@ -1,45 +1,44 @@ using System.Text; -namespace LogExpert.Core.EventArguments +namespace LogExpert.Core.EventArguments; + +public class GuiStateArgs : System.EventArgs { - public class GuiStateArgs : System.EventArgs - { - #region Properties + #region Properties - public bool TimeshiftEnabled { get; set; } + public bool TimeshiftEnabled { get; set; } - public bool FollowTail { get; set; } + public bool FollowTail { get; set; } - public bool MenuEnabled { get; set; } = true; + public bool MenuEnabled { get; set; } = true; - public string TimeshiftText { get; set; } = string.Empty; + public string TimeshiftText { get; set; } = string.Empty; - public bool TimeshiftPossible { get; set; } = false; + public bool TimeshiftPossible { get; set; } - public bool MultiFileEnabled { get; set; } = true; + public bool MultiFileEnabled { get; set; } = true; - public bool FilterEnabled { get; set; } = true; + public bool FilterEnabled { get; set; } = true; - public bool CellSelectMode { get; set; } = false; + public bool CellSelectMode { get; set; } - public Encoding CurrentEncoding { get; set; } + public Encoding CurrentEncoding { get; set; } - public DateTime Timestamp { get; set; } + public DateTime Timestamp { get; set; } - public DateTime MinTimestamp { get; set; } + public DateTime MinTimestamp { get; set; } - public DateTime MaxTimestamp { get; set; } + public DateTime MaxTimestamp { get; set; } - public bool ShowBookmarkBubbles { get; set; } + public bool ShowBookmarkBubbles { get; set; } - public bool IsMultiFileActive { get; set; } + public bool IsMultiFileActive { get; set; } - public bool ShowHiddenLines { get; set; } = true; + public bool ShowHiddenLines { get; set; } = true; - public string HighlightGroupName { get; set; } = string.Empty; + public string HighlightGroupName { get; set; } = string.Empty; - public bool ColumnFinderVisible { get; set; } + public bool ColumnFinderVisible { get; set; } - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/EventArguments/LoadFileEventArgs.cs b/src/LogExpert.Core/EventArguments/LoadFileEventArgs.cs index 18f786b9..b7daa31a 100644 --- a/src/LogExpert.Core/EventArguments/LoadFileEventArgs.cs +++ b/src/LogExpert.Core/EventArguments/LoadFileEventArgs.cs @@ -1,4 +1,3 @@ -namespace LogExpert.Core.EventArguments -{ - public record LoadFileEventArgs(string FileName, long ReadPos, bool Finished, long FileSize, bool NewFile); -} \ No newline at end of file +namespace LogExpert.Core.EventArguments; + +public record LoadFileEventArgs(string FileName, long ReadPos, bool Finished, long FileSize, bool NewFile); \ No newline at end of file diff --git a/src/LogExpert.Core/EventArguments/OverlayEventArgs.cs b/src/LogExpert.Core/EventArguments/OverlayEventArgs.cs index ef826147..91faf48b 100644 --- a/src/LogExpert.Core/EventArguments/OverlayEventArgs.cs +++ b/src/LogExpert.Core/EventArguments/OverlayEventArgs.cs @@ -1,13 +1,12 @@ using LogExpert.Core.Entities; -namespace LogExpert.Core.EventArguments +namespace LogExpert.Core.EventArguments; + +public class OverlayEventArgs(BookmarkOverlay overlay) : System.EventArgs { - public class OverlayEventArgs(BookmarkOverlay overlay) : System.EventArgs - { - #region Properties + #region Properties - public BookmarkOverlay BookmarkOverlay { get; set; } = overlay; + public BookmarkOverlay BookmarkOverlay { get; set; } = overlay; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/EventArguments/PatternArgs.cs b/src/LogExpert.Core/EventArguments/PatternArgs.cs index b8b63a60..3cfe2e69 100644 --- a/src/LogExpert.Core/EventArguments/PatternArgs.cs +++ b/src/LogExpert.Core/EventArguments/PatternArgs.cs @@ -1,21 +1,20 @@ -namespace LogExpert.Core.EventArguments +namespace LogExpert.Core.EventArguments; + +public class PatternArgs { - public class PatternArgs - { - #region Properties + #region Properties - public int EndLine { get; set; } = 0; + public int EndLine { get; set; } - public int Fuzzy { get; set; } = 6; + public int Fuzzy { get; set; } = 6; - public int MaxDiffInBlock { get; set; } = 5; + public int MaxDiffInBlock { get; set; } = 5; - public int MaxMisses { get; set; } = 5; + public int MaxMisses { get; set; } = 5; - public int MinWeight { get; set; } = 15; + public int MinWeight { get; set; } = 15; - public int StartLine { get; set; } = 0; + public int StartLine { get; set; } - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/EventArguments/ProgressEventArgs.cs b/src/LogExpert.Core/EventArguments/ProgressEventArgs.cs index f91c15fc..58db9efb 100644 --- a/src/LogExpert.Core/EventArguments/ProgressEventArgs.cs +++ b/src/LogExpert.Core/EventArguments/ProgressEventArgs.cs @@ -1,17 +1,16 @@ -namespace LogExpert.Core.EventArguments +namespace LogExpert.Core.EventArguments; + +public class ProgressEventArgs : System.EventArgs { - public class ProgressEventArgs : System.EventArgs - { - #region Properties + #region Properties - public int Value { get; set; } + public int Value { get; set; } - public int MinValue { get; set; } + public int MinValue { get; set; } - public int MaxValue { get; set; } + public int MaxValue { get; set; } - public bool Visible { get; set; } + public bool Visible { get; set; } - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/EventArguments/SelectLineEventArgs.cs b/src/LogExpert.Core/EventArguments/SelectLineEventArgs.cs index b667872b..ac94ccfc 100644 --- a/src/LogExpert.Core/EventArguments/SelectLineEventArgs.cs +++ b/src/LogExpert.Core/EventArguments/SelectLineEventArgs.cs @@ -1,11 +1,10 @@ -namespace LogExpert.Core.EventArguments +namespace LogExpert.Core.EventArguments; + +public class SelectLineEventArgs(int line) : System.EventArgs { - public class SelectLineEventArgs(int line) : System.EventArgs - { - #region Properties + #region Properties - public int Line { get; } = line; + public int Line { get; } = line; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/EventArguments/StatusEventArgs.cs b/src/LogExpert.Core/EventArguments/StatusEventArgs.cs index 43d6f99d..21786a3b 100644 --- a/src/LogExpert.Core/EventArguments/StatusEventArgs.cs +++ b/src/LogExpert.Core/EventArguments/StatusEventArgs.cs @@ -1,33 +1,32 @@ -namespace LogExpert.Core.EventArguments +namespace LogExpert.Core.EventArguments; + +public class StatusLineEventArgs : System.EventArgs { - public class StatusLineEventArgs : System.EventArgs - { - #region Properties + #region Properties - public long FileSize { get; set; } = 0; + public long FileSize { get; set; } - public string StatusText { get; set; } = string.Empty; + public string StatusText { get; set; } = string.Empty; - public int LineCount { get; set; } = 0; + public int LineCount { get; set; } - public int CurrentLineNum { get; set; } = 0; + public int CurrentLineNum { get; set; } - #endregion + #endregion - #region Public methods + #region Public methods - public StatusLineEventArgs Clone() + public StatusLineEventArgs Clone() + { + StatusLineEventArgs e = new() { - StatusLineEventArgs e = new() - { - StatusText = StatusText, - CurrentLineNum = CurrentLineNum, - LineCount = LineCount, - FileSize = FileSize - }; - return e; - } - - #endregion + StatusText = StatusText, + CurrentLineNum = CurrentLineNum, + LineCount = LineCount, + FileSize = FileSize + }; + return e; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/EventArguments/SyncModeEventArgs.cs b/src/LogExpert.Core/EventArguments/SyncModeEventArgs.cs index f595c0d4..97378d4c 100644 --- a/src/LogExpert.Core/EventArguments/SyncModeEventArgs.cs +++ b/src/LogExpert.Core/EventArguments/SyncModeEventArgs.cs @@ -1,11 +1,10 @@ -namespace LogExpert.Core.EventArguments +namespace LogExpert.Core.EventArguments; + +public class SyncModeEventArgs(bool isSynced) : System.EventArgs { - public class SyncModeEventArgs(bool isSynced) : System.EventArgs - { - #region Properties + #region Properties - public bool IsTimeSynced { get; } = isSynced; + public bool IsTimeSynced { get; } = isSynced; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/EventHandlers/EventHandlers.cs b/src/LogExpert.Core/EventHandlers/EventHandlers.cs index 2254b17a..63f44923 100644 --- a/src/LogExpert.Core/EventHandlers/EventHandlers.cs +++ b/src/LogExpert.Core/EventHandlers/EventHandlers.cs @@ -1,8 +1,7 @@ using LogExpert.Core.Entities; using LogExpert.Core.EventArguments; -namespace LogExpert.Core.EventHandlers -{ - public delegate void ConfigChangedEventHandler(object sender, ConfigChangedEventArgs e); - public delegate void FileSizeChangedEventHandler(object sender, LogEventArgs e); -} +namespace LogExpert.Core.EventHandlers; + +public delegate void ConfigChangedEventHandler(object sender, ConfigChangedEventArgs e); +public delegate void FileSizeChangedEventHandler(object sender, LogEventArgs e); diff --git a/src/LogExpert.Core/Extensions/IEnumerable.cs b/src/LogExpert.Core/Extensions/IEnumerable.cs index 3a7524d9..d8357fb4 100644 --- a/src/LogExpert.Core/Extensions/IEnumerable.cs +++ b/src/LogExpert.Core/Extensions/IEnumerable.cs @@ -1,25 +1,24 @@ -namespace LogExpert.Core.Extensions +namespace LogExpert.Core.Extensions; + +public static class Extensions { - public static class Extensions + public static bool IsEmpty(this IEnumerable collection) { - public static bool IsEmpty(this IEnumerable collection) + if (collection == null) { - if (collection == null) - { - return true; - } - - return !collection.Any(); + return true; } - public static bool IsEmpty(this IList list) - { - if (list == null) - { - return true; - } + return !collection.Any(); + } - return list.Count == 0; + public static bool IsEmpty(this IList list) + { + if (list == null) + { + return true; } + + return list.Count == 0; } } \ No newline at end of file diff --git a/src/LogExpert.Core/Interface/IBackgroundProcessCancelHandler.cs b/src/LogExpert.Core/Interface/IBackgroundProcessCancelHandler.cs index 132589e0..b1a0ce37 100644 --- a/src/LogExpert.Core/Interface/IBackgroundProcessCancelHandler.cs +++ b/src/LogExpert.Core/Interface/IBackgroundProcessCancelHandler.cs @@ -1,18 +1,17 @@ -namespace LogExpert.Core.Interface +namespace LogExpert.Core.Interface; + +/// +/// Interface which can register at the LogWindow to be informed of pressing ESC. +/// Used e.g. for cancelling a filter. +/// +public interface IBackgroundProcessCancelHandler { + #region Public methods + /// - /// Interface which can register at the LogWindow to be informed of pressing ESC. - /// Used e.g. for cancelling a filter. + /// Called when ESC was pressed. /// - public interface IBackgroundProcessCancelHandler - { - #region Public methods - - /// - /// Called when ESC was pressed. - /// - void EscapePressed(); + void EscapePressed(); - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Interface/IConfigManager.cs b/src/LogExpert.Core/Interface/IConfigManager.cs index e2de05f0..57638394 100644 --- a/src/LogExpert.Core/Interface/IConfigManager.cs +++ b/src/LogExpert.Core/Interface/IConfigManager.cs @@ -2,21 +2,20 @@ using LogExpert.Core.EventArguments; using LogExpert.Core.EventHandlers; -namespace LogExpert.Core.Interface +namespace LogExpert.Core.Interface; + +//TODO: Add documentation +public interface IConfigManager { - //TODO: Add documentation - public interface IConfigManager - { - Settings Settings { get; } - string PortableModeDir { get; } - string ConfigDir { get; } - IConfigManager Instance { get; } - string PortableModeSettingsFileName { get; } - void Export(FileInfo fileInfo, SettingsFlags highlightSettings); - void Export(FileInfo fileInfo); - void Import(FileInfo fileInfo, ExportImportFlags importFlags); - void ImportHighlightSettings(FileInfo fileInfo, ExportImportFlags importFlags); - event ConfigChangedEventHandler ConfigChanged; //TODO: All handlers that are public shoulld be in Core - void Save(SettingsFlags flags); - } + Settings Settings { get; } + string PortableModeDir { get; } + string ConfigDir { get; } + IConfigManager Instance { get; } + string PortableModeSettingsFileName { get; } + void Export(FileInfo fileInfo, SettingsFlags highlightSettings); + void Export(FileInfo fileInfo); + void Import(FileInfo fileInfo, ExportImportFlags importFlags); + void ImportHighlightSettings(FileInfo fileInfo, ExportImportFlags importFlags); + event ConfigChangedEventHandler ConfigChanged; //TODO: All handlers that are public shoulld be in Core + void Save(SettingsFlags flags); } \ No newline at end of file diff --git a/src/LogExpert.Core/Interface/IFileViewContext.cs b/src/LogExpert.Core/Interface/IFileViewContext.cs index da0b33f3..15ae41b2 100644 --- a/src/LogExpert.Core/Interface/IFileViewContext.cs +++ b/src/LogExpert.Core/Interface/IFileViewContext.cs @@ -1,10 +1,9 @@ using LogExpert.Core.Entities; -namespace LogExpert.Core.Interface +namespace LogExpert.Core.Interface; + +public interface IFileViewContext { - public interface IFileViewContext - { - ILogView LogView { get; } - ILogPaintContext LogPaintContext { get; } - } + ILogView LogView { get; } + ILogPaintContext LogPaintContext { get; } } \ No newline at end of file diff --git a/src/LogExpert.Core/Interface/ILogExpertProxy.cs b/src/LogExpert.Core/Interface/ILogExpertProxy.cs index 1bf43bcc..be0ed347 100644 --- a/src/LogExpert.Core/Interface/ILogExpertProxy.cs +++ b/src/LogExpert.Core/Interface/ILogExpertProxy.cs @@ -1,38 +1,37 @@ -namespace LogExpert.Core.Interface +namespace LogExpert.Core.Interface; + +public interface ILogExpertProxy { - public interface ILogExpertProxy - { - #region Public methods + #region Public methods - /// - /// Load the given files into the existing window. - /// - /// - void LoadFiles(string[] fileNames); + /// + /// Load the given files into the existing window. + /// + /// + void LoadFiles(string[] fileNames); - /// - /// Open a new LogExpert window and load the given files. - /// - /// - void NewWindow(string[] fileNames); + /// + /// Open a new LogExpert window and load the given files. + /// + /// + void NewWindow(string[] fileNames); - /// - /// load given files into the locked window or open a new window if no window is locked. - /// - /// - void NewWindowOrLockedWindow(string[] fileNames); + /// + /// load given files into the locked window or open a new window if no window is locked. + /// + /// + void NewWindowOrLockedWindow(string[] fileNames); - /// - /// Called from LogTabWindow when the window is about to be closed. - /// - /// - void WindowClosed(ILogTabWindow logWin); + /// + /// Called from LogTabWindow when the window is about to be closed. + /// + /// + void WindowClosed(ILogTabWindow logWin); - int GetLogWindowCount(); + int GetLogWindowCount(); - #endregion + #endregion - //void BroadcastSettingsChanged(Object cookie); - } + //void BroadcastSettingsChanged(Object cookie); } \ No newline at end of file diff --git a/src/LogExpert.Core/Interface/ILogPaintContext.cs b/src/LogExpert.Core/Interface/ILogPaintContext.cs index 2fae38fa..2cf7ad03 100644 --- a/src/LogExpert.Core/Interface/ILogPaintContext.cs +++ b/src/LogExpert.Core/Interface/ILogPaintContext.cs @@ -1,6 +1,5 @@ -namespace LogExpert.Core.Interface +namespace LogExpert.Core.Interface; + +public interface ILogPaintContext { - public interface ILogPaintContext - { - } } \ No newline at end of file diff --git a/src/LogExpert.Core/Interface/ILogStreamReader.cs b/src/LogExpert.Core/Interface/ILogStreamReader.cs index 11ce40f2..cfe4af05 100644 --- a/src/LogExpert.Core/Interface/ILogStreamReader.cs +++ b/src/LogExpert.Core/Interface/ILogStreamReader.cs @@ -1,24 +1,23 @@ using System.Text; -namespace LogExpert.Core.Interface +namespace LogExpert.Core.Interface; + +public interface ILogStreamReader : IDisposable { - public interface ILogStreamReader : IDisposable - { - #region Properties + #region Properties - long Position { get; set; } + long Position { get; set; } - bool IsBufferComplete { get; } + bool IsBufferComplete { get; } - Encoding Encoding { get; } + Encoding Encoding { get; } - #endregion + #endregion - #region Public methods + #region Public methods - int ReadChar(); - string ReadLine(); + int ReadChar(); + string ReadLine(); - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Interface/ILogView.cs b/src/LogExpert.Core/Interface/ILogView.cs index c1009b55..d56bc759 100644 --- a/src/LogExpert.Core/Interface/ILogView.cs +++ b/src/LogExpert.Core/Interface/ILogView.cs @@ -1,24 +1,23 @@ -namespace LogExpert.Core.Interface +namespace LogExpert.Core.Interface; + +/// +/// Methods to control the LogWindow from other views. +/// +public interface ILogView { - /// - /// Methods to control the LogWindow from other views. - /// - public interface ILogView - { - #region Properties + #region Properties - ILogLineColumnizer CurrentColumnizer { get; } - string FileName { get; } + ILogLineColumnizer CurrentColumnizer { get; } + string FileName { get; } - #endregion + #endregion - #region Public methods + #region Public methods - void SelectLogLine(int lineNumber); - void SelectAndEnsureVisible(int line, bool triggerSyncCall); - void RefreshLogView(); - void DeleteBookmarks(List lineNumList); + void SelectLogLine(int lineNumber); + void SelectAndEnsureVisible(int line, bool triggerSyncCall); + void RefreshLogView(); + void DeleteBookmarks(List lineNumList); - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Interface/IPluginRegistry.cs b/src/LogExpert.Core/Interface/IPluginRegistry.cs index 82f42f71..bca099ff 100644 --- a/src/LogExpert.Core/Interface/IPluginRegistry.cs +++ b/src/LogExpert.Core/Interface/IPluginRegistry.cs @@ -1,10 +1,9 @@ -namespace LogExpert.Core.Interface +namespace LogExpert.Core.Interface; + +//TODO: Add documentation +public interface IPluginRegistry { - //TODO: Add documentation - public interface IPluginRegistry - { - IList RegisteredColumnizers { get; } + IList RegisteredColumnizers { get; } - IFileSystemPlugin FindFileSystemForUri(string fileNameOrUri); - } + IFileSystemPlugin FindFileSystemForUri (string fileNameOrUri); } \ No newline at end of file diff --git a/src/LogExpert.Core/Interface/ISharedToolWindow.cs b/src/LogExpert.Core/Interface/ISharedToolWindow.cs index 3178206d..1d2a80e8 100644 --- a/src/LogExpert.Core/Interface/ISharedToolWindow.cs +++ b/src/LogExpert.Core/Interface/ISharedToolWindow.cs @@ -1,31 +1,30 @@ using LogExpert.Core.Config; -namespace LogExpert.Core.Interface +namespace LogExpert.Core.Interface; + +/// +/// Interface to be implemented by tools windows that are shared across multiple log files. +/// The implementor will be called whenever the current log file changes. So it can draw new content +/// according to the current active log file. +/// +public interface ISharedToolWindow { + #region Public methods + /// - /// Interface to be implemented by tools windows that are shared across multiple log files. - /// The implementor will be called whenever the current log file changes. So it can draw new content - /// according to the current active log file. + /// Called when a file becomes the active file (e.g. when user selects a tab). /// - public interface ISharedToolWindow - { - #region Public methods - - /// - /// Called when a file becomes the active file (e.g. when user selects a tab). - /// - /// - void SetCurrentFile(IFileViewContext ctx); + /// + void SetCurrentFile(IFileViewContext ctx); - /// - /// Called whenever the current file has been changed. - /// - void FileChanged(); + /// + /// Called whenever the current file has been changed. + /// + void FileChanged(); - void SetColumnizer(ILogLineColumnizer columnizer); + void SetColumnizer(ILogLineColumnizer columnizer); - void PreferencesChanged(Preferences newPreferences, bool isLoadTime, SettingsFlags flags); + void PreferencesChanged(Preferences newPreferences, bool isLoadTime, SettingsFlags flags); - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert.Core/Structs/ActEntry.cs b/src/LogExpert.Core/Structs/ActEntry.cs index b3ea1331..1328fc1a 100644 --- a/src/LogExpert.Core/Structs/ActEntry.cs +++ b/src/LogExpert.Core/Structs/ActEntry.cs @@ -1,9 +1,8 @@ -namespace LogExpert.Core.Structs +namespace LogExpert.Core.Structs; + +public struct ActEntry { - public struct ActEntry - { - public string Name { get; set; } + public string Name { get; set; } - public IKeywordAction Plugin { get; set; } - } + public IKeywordAction Plugin { get; set; } } \ No newline at end of file diff --git a/src/LogExpert.Tests/BufferShiftTest.cs b/src/LogExpert.Tests/BufferShiftTest.cs index cde669e0..bbbefee5 100644 --- a/src/LogExpert.Tests/BufferShiftTest.cs +++ b/src/LogExpert.Tests/BufferShiftTest.cs @@ -1,146 +1,147 @@ -using LogExpert.Core.Classes.Log; -using LogExpert.Core.Entities; -using LogExpert.PluginRegistry.FileSystem; -using NUnit.Framework; using System.Collections.Generic; using System.Linq; using System.Text; -namespace LogExpert.Tests +using LogExpert.Core.Classes.Log; +using LogExpert.Core.Entities; +using LogExpert.PluginRegistry.FileSystem; + +using NUnit.Framework; + +namespace LogExpert.Tests; + +[TestFixture] +internal class BufferShiftTest : RolloverHandlerTestBase { - [TestFixture] - internal class BufferShiftTest : RolloverHandlerTestBase + [TearDown] + public void TearDown () { - [TearDown] - public void TearDown() - { - Cleanup(); - } + Cleanup(); + } + + [OneTimeSetUp] + public void Boot () + { + Cleanup(); + } - [OneTimeSetUp] - public void Boot() + + [Test] + public void TestShiftBuffers1 () + { + var linesPerFile = 10; + MultiFileOptions options = new() { - Cleanup(); - } + MaxDayTry = 0, + FormatPattern = "*$J(.)" + }; + LinkedList files = CreateTestFilesWithoutDate(); + EncodingOptions encodingOptions = new() + { + Encoding = Encoding.Default + }; + PluginRegistry.PluginRegistry.Instance.Create(testDirectory.FullName, 500); + LogfileReader reader = new(files.Last.Value, encodingOptions, true, 40, 50, options, PluginRegistry.PluginRegistry.Instance); + reader.ReadFiles(); - [Test] - public void TestShiftBuffers1() + IList lil = reader.GetLogFileInfoList(); + Assert.That(lil.Count, Is.EqualTo(files.Count)); + + LinkedList.Enumerator enumerator = files.GetEnumerator(); + enumerator.MoveNext(); + + foreach (LogFileInfo li in lil.Cast()) { - int linesPerFile = 10; - MultiFileOptions options = new() - { - MaxDayTry = 0, - FormatPattern = "*$J(.)" - }; - LinkedList files = CreateTestFilesWithoutDate(); - EncodingOptions encodingOptions = new() - { - Encoding = Encoding.Default - }; - - PluginRegistry.PluginRegistry.Instance.Create(testDirectory.FullName, 500); - LogfileReader reader = new(files.Last.Value, encodingOptions, true, 40, 50, options, PluginRegistry.PluginRegistry.Instance); - reader.ReadFiles(); - - IList lil = reader.GetLogFileInfoList(); - Assert.That(lil.Count, Is.EqualTo(files.Count)); - - LinkedList.Enumerator enumerator = files.GetEnumerator(); + var fileName = enumerator.Current; + Assert.That(li.FullName, Is.EqualTo(fileName)); enumerator.MoveNext(); + } + var oldCount = lil.Count; - foreach (LogFileInfo li in lil.Cast()) - { - string fileName = enumerator.Current; - Assert.That(li.FullName, Is.EqualTo(fileName)); - enumerator.MoveNext(); - } - int oldCount = lil.Count; - - // Simulate rollover - // - files = RolloverSimulation(files, "*$J(.)", false); + // Simulate rollover + // + files = RolloverSimulation(files, "*$J(.)", false); - // Simulate rollover detection - // - reader.ShiftBuffers(); + // Simulate rollover detection + // + reader.ShiftBuffers(); - lil = reader.GetLogFileInfoList(); - Assert.That(lil.Count, Is.EqualTo(oldCount + 1)); + lil = reader.GetLogFileInfoList(); + Assert.That(lil.Count, Is.EqualTo(oldCount + 1)); - Assert.That(reader.LineCount, Is.EqualTo(linesPerFile * lil.Count)); + Assert.That(reader.LineCount, Is.EqualTo(linesPerFile * lil.Count)); - // Check if rollover'd file names have been handled by LogfileReader - // - Assert.That(lil.Count, Is.EqualTo(files.Count)); - enumerator = files.GetEnumerator(); - enumerator.MoveNext(); - foreach (LogFileInfo li in lil) - { - string fileName = enumerator.Current; - Assert.That(li.FullName, Is.EqualTo(fileName)); - enumerator.MoveNext(); - } - - // Check if file buffers have correct files. Assuming here that one buffer fits for a - // complete file - // - enumerator = files.GetEnumerator(); + // Check if rollover'd file names have been handled by LogfileReader + // + Assert.That(lil.Count, Is.EqualTo(files.Count)); + enumerator = files.GetEnumerator(); + enumerator.MoveNext(); + foreach (LogFileInfo li in lil) + { + var fileName = enumerator.Current; + Assert.That(li.FullName, Is.EqualTo(fileName)); enumerator.MoveNext(); - IList logBuffers = reader.GetBufferList(); - int startLine = 0; - foreach (LogBuffer logBuffer in logBuffers) - { - Assert.That(enumerator.Current, Is.EqualTo(logBuffer.FileInfo.FullName)); - Assert.That(logBuffer.StartLine, Is.EqualTo(startLine)); - startLine += 10; - enumerator.MoveNext(); - } - - // Checking file content - // - enumerator = files.GetEnumerator(); + } + + // Check if file buffers have correct files. Assuming here that one buffer fits for a + // complete file + // + enumerator = files.GetEnumerator(); + enumerator.MoveNext(); + IList logBuffers = reader.GetBufferList(); + var startLine = 0; + foreach (LogBuffer logBuffer in logBuffers) + { + Assert.That(enumerator.Current, Is.EqualTo(logBuffer.FileInfo.FullName)); + Assert.That(logBuffer.StartLine, Is.EqualTo(startLine)); + startLine += 10; enumerator.MoveNext(); - enumerator.MoveNext(); // move to 2nd entry. The first file now contains 2nd file's content (because rollover) - logBuffers = reader.GetBufferList(); - int i; - for (i = 0; i < logBuffers.Count - 2; ++i) - { - LogBuffer logBuffer = logBuffers[i]; - ILogLine line = logBuffer.GetLineOfBlock(0); - Assert.That(line.FullLine.Contains(enumerator.Current)); - enumerator.MoveNext(); - } + } + + // Checking file content + // + enumerator = files.GetEnumerator(); + enumerator.MoveNext(); + enumerator.MoveNext(); // move to 2nd entry. The first file now contains 2nd file's content (because rollover) + logBuffers = reader.GetBufferList(); + int i; + for (i = 0; i < logBuffers.Count - 2; ++i) + { + LogBuffer logBuffer = logBuffers[i]; + ILogLine line = logBuffer.GetLineOfBlock(0); + Assert.That(line.FullLine.Contains(enumerator.Current)); enumerator.MoveNext(); - // the last 2 files now contain the content of the previously watched file - for (; i < logBuffers.Count; ++i) - { - LogBuffer logBuffer = logBuffers[i]; - ILogLine line = logBuffer.GetLineOfBlock(0); - Assert.That(line.FullLine.Contains(enumerator.Current)); - } - - oldCount = lil.Count; - - // Simulate rollover again - now latest file will be deleted (simulates logger's rollover history limit) - // - files = RolloverSimulation(files, "*$J(.)", true); - - // Simulate rollover detection - // - reader.ShiftBuffers(); - lil = reader.GetLogFileInfoList(); - - Assert.That(lil.Count, Is.EqualTo(oldCount)); // same count because oldest file is deleted - Assert.That(lil.Count, Is.EqualTo(files.Count)); - Assert.That(reader.LineCount, Is.EqualTo(linesPerFile * lil.Count)); - - // Check first line to see if buffers are correct - // - ILogLine firstLine = reader.GetLogLine(0); - string[] names = new string[files.Count]; - files.CopyTo(names, 0); - Assert.That(firstLine.FullLine.Contains(names[2])); } + enumerator.MoveNext(); + // the last 2 files now contain the content of the previously watched file + for (; i < logBuffers.Count; ++i) + { + LogBuffer logBuffer = logBuffers[i]; + ILogLine line = logBuffer.GetLineOfBlock(0); + Assert.That(line.FullLine.Contains(enumerator.Current)); + } + + oldCount = lil.Count; + + // Simulate rollover again - now latest file will be deleted (simulates logger's rollover history limit) + // + files = RolloverSimulation(files, "*$J(.)", true); + + // Simulate rollover detection + // + reader.ShiftBuffers(); + lil = reader.GetLogFileInfoList(); + + Assert.That(lil.Count, Is.EqualTo(oldCount)); // same count because oldest file is deleted + Assert.That(lil.Count, Is.EqualTo(files.Count)); + Assert.That(reader.LineCount, Is.EqualTo(linesPerFile * lil.Count)); + + // Check first line to see if buffers are correct + // + ILogLine firstLine = reader.GetLogLine(0); + var names = new string[files.Count]; + files.CopyTo(names, 0); + Assert.That(firstLine.FullLine.Contains(names[2])); } } \ No newline at end of file diff --git a/src/LogExpert.Tests/CSVColumnizerTest.cs b/src/LogExpert.Tests/CSVColumnizerTest.cs index 5e9c2de0..1c9ccce1 100644 --- a/src/LogExpert.Tests/CSVColumnizerTest.cs +++ b/src/LogExpert.Tests/CSVColumnizerTest.cs @@ -6,28 +6,27 @@ using System; using System.IO; -namespace LogExpert.Tests +namespace LogExpert.Tests; + +[TestFixture] +public class CSVColumnizerTest { - [TestFixture] - public class CSVColumnizerTest + [TestCase(@".\TestData\organizations-10000.csv", new[] { "Index", "Organization Id", "Name", "Website", "Country", "Description", "Founded", "Industry", "Number of employees" })] + [TestCase(@".\TestData\organizations-1000.csv", new[] { "Index", "Organization Id", "Name", "Website", "Country", "Description", "Founded", "Industry", "Number of employees" })] + [TestCase(@".\TestData\people-10000.csv", new[] { "Index", "User Id", "First Name", "Last Name", "Sex", "Email", "Phone", "Date of birth", "Job Title" })] + public void Instantiat_CSVFile_BuildCorrectColumnizer(string filename, string[] expectedHeaders) { - [TestCase(@".\TestData\organizations-10000.csv", new[] { "Index", "Organization Id", "Name", "Website", "Country", "Description", "Founded", "Industry", "Number of employees" })] - [TestCase(@".\TestData\organizations-1000.csv", new[] { "Index", "Organization Id", "Name", "Website", "Country", "Description", "Founded", "Industry", "Number of employees" })] - [TestCase(@".\TestData\people-10000.csv", new[] { "Index", "User Id", "First Name", "Last Name", "Sex", "Email", "Phone", "Date of birth", "Job Title" })] - public void Instantiat_CSVFile_BuildCorrectColumnizer(string filename, string[] expectedHeaders) + CsvColumnizer.CsvColumnizer csvColumnizer = new(); + var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, filename); + LogfileReader reader = new(path, new EncodingOptions(), true, 40, 50, new MultiFileOptions(), PluginRegistry.PluginRegistry.Instance); + reader.ReadFiles(); + ILogLine line = reader.GetLogLine(0); + IColumnizedLogLine logline = new ColumnizedLogLine(); + if (line != null) { - CsvColumnizer.CsvColumnizer csvColumnizer = new(); - string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, filename); - LogfileReader reader = new(path, new EncodingOptions(), true, 40, 50, new MultiFileOptions(), PluginRegistry.PluginRegistry.Instance); - reader.ReadFiles(); - ILogLine line = reader.GetLogLine(0); - IColumnizedLogLine logline = new ColumnizedLogLine(); - if (line != null) - { - logline = csvColumnizer.SplitLine(null, line); - } - string expectedResult = string.Join(",", expectedHeaders); - Assert.That(logline.LogLine.FullLine, Is.EqualTo(expectedResult)); + logline = csvColumnizer.SplitLine(null, line); } + var expectedResult = string.Join(",", expectedHeaders); + Assert.That(logline.LogLine.FullLine, Is.EqualTo(expectedResult)); } } diff --git a/src/LogExpert.Tests/ColumnizerPickerTest.cs b/src/LogExpert.Tests/ColumnizerPickerTest.cs index 585a99e3..f6204673 100644 --- a/src/LogExpert.Tests/ColumnizerPickerTest.cs +++ b/src/LogExpert.Tests/ColumnizerPickerTest.cs @@ -7,111 +7,110 @@ using System; using System.IO; -namespace LogExpert.Tests +namespace LogExpert.Tests; + +/// +/// Summary description for AutoColumnizerTest +/// +[TestFixture] +public class ColumnizerPickerTest { - /// - /// Summary description for AutoColumnizerTest - /// - [TestFixture] - public class ColumnizerPickerTest + [TestCase("Square Bracket Columnizer", "30/08/2018 08:51:42.712 [TRACE] [a] hello", "30/08/2018 08:51:42.712 [DATAIO] [b] world", null, null, null)] + [TestCase("Square Bracket Columnizer", "30/08/2018 08:51:42.712 [TRACE] hello", "30/08/2018 08:51:42.712 [DATAIO][] world", null, null, null)] + [TestCase("Square Bracket Columnizer", "", "30/08/2018 08:51:42.712 [TRACE] hello", "30/08/2018 08:51:42.712 [TRACE] hello", "[DATAIO][b][c] world", null)] + [TestCase("Timestamp Columnizer", "30/08/2018 08:51:42.712 no bracket 1", "30/08/2018 08:51:42.712 no bracket 2", "30/08/2018 08:51:42.712 [TRACE] with bracket 1", "30/08/2018 08:51:42.712 [TRACE] with bracket 2", "no bracket 3")] + public void FindColumnizer_ReturnCorrectColumnizer(string expectedColumnizerName, string line0, string line1, string line2, string line3, string line4) { - [TestCase("Square Bracket Columnizer", "30/08/2018 08:51:42.712 [TRACE] [a] hello", "30/08/2018 08:51:42.712 [DATAIO] [b] world", null, null, null)] - [TestCase("Square Bracket Columnizer", "30/08/2018 08:51:42.712 [TRACE] hello", "30/08/2018 08:51:42.712 [DATAIO][] world", null, null, null)] - [TestCase("Square Bracket Columnizer", "", "30/08/2018 08:51:42.712 [TRACE] hello", "30/08/2018 08:51:42.712 [TRACE] hello", "[DATAIO][b][c] world", null)] - [TestCase("Timestamp Columnizer", "30/08/2018 08:51:42.712 no bracket 1", "30/08/2018 08:51:42.712 no bracket 2", "30/08/2018 08:51:42.712 [TRACE] with bracket 1", "30/08/2018 08:51:42.712 [TRACE] with bracket 2", "no bracket 3")] - public void FindColumnizer_ReturnCorrectColumnizer(string expectedColumnizerName, string line0, string line1, string line2, string line3, string line4) + var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "test"); + + Mock autoLogLineColumnizerCallbackMock = new(); + + autoLogLineColumnizerCallbackMock.Setup(a => a.GetLogLine(0)).Returns(new TestLogLine() { - string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "test"); - - Mock autoLogLineColumnizerCallbackMock = new(); - - autoLogLineColumnizerCallbackMock.Setup(a => a.GetLogLine(0)).Returns(new TestLogLine() - { - FullLine = line0, - LineNumber = 0 - }); - - autoLogLineColumnizerCallbackMock.Setup(a => a.GetLogLine(1)).Returns(new TestLogLine() - { - FullLine = line1, - LineNumber = 1 - }); - - autoLogLineColumnizerCallbackMock.Setup(a => a.GetLogLine(2)).Returns(new TestLogLine() - { - FullLine = line2, - LineNumber = 2 - }); - - autoLogLineColumnizerCallbackMock.Setup(a => a.GetLogLine(3)).Returns(new TestLogLine() - { - FullLine = line3, - LineNumber = 3 - }); - autoLogLineColumnizerCallbackMock.Setup(a => a.GetLogLine(4)).Returns(new TestLogLine() - { - FullLine = line4, - LineNumber = 4 - }); - - var result = ColumnizerPicker.FindColumnizer(path, autoLogLineColumnizerCallbackMock.Object, PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers); - - Assert.That(result.GetName(), Is.EqualTo(expectedColumnizerName)); - } - - - [TestCase(@".\TestData\JsonColumnizerTest_01.txt", typeof(JsonCompactColumnizer))] - [TestCase(@".\TestData\SquareBracketColumnizerTest_02.txt", typeof(SquareBracketColumnizer))] - public void FindReplacementForAutoColumnizer_ValidTextFile_ReturnCorrectColumnizer( - string fileName, Type columnizerType) + FullLine = line0, + LineNumber = 0 + }); + + autoLogLineColumnizerCallbackMock.Setup(a => a.GetLogLine(1)).Returns(new TestLogLine() + { + FullLine = line1, + LineNumber = 1 + }); + + autoLogLineColumnizerCallbackMock.Setup(a => a.GetLogLine(2)).Returns(new TestLogLine() { - string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName); - LogfileReader reader = new(path, new EncodingOptions(), true, 40, 50, new MultiFileOptions(), PluginRegistry.PluginRegistry.Instance); - reader.ReadFiles(); + FullLine = line2, + LineNumber = 2 + }); - Mock autoColumnizer = new(); - autoColumnizer.Setup(a => a.GetName()).Returns("Auto Columnizer"); + autoLogLineColumnizerCallbackMock.Setup(a => a.GetLogLine(3)).Returns(new TestLogLine() + { + FullLine = line3, + LineNumber = 3 + }); + autoLogLineColumnizerCallbackMock.Setup(a => a.GetLogLine(4)).Returns(new TestLogLine() + { + FullLine = line4, + LineNumber = 4 + }); - // TODO: When DI container is ready, we can mock this set up. - PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers.Add(new JsonCompactColumnizer()); - var result = ColumnizerPicker.FindReplacementForAutoColumnizer(fileName, reader, autoColumnizer.Object, PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers); + var result = ColumnizerPicker.FindColumnizer(path, autoLogLineColumnizerCallbackMock.Object, PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers); - Assert.That(columnizerType, Is.EqualTo(result.GetType())); - } + Assert.That(result.GetName(), Is.EqualTo(expectedColumnizerName)); + } - [TestCase(@".\TestData\FileNotExists.txt", typeof(DefaultLogfileColumnizer))] - public void DecideColumnizerByName_WhenReaderIsNotReady_ReturnCorrectColumnizer( - string fileName, Type columnizerType) - { - string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName); - // TODO: When DI container is ready, we can mock this set up. - PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers.Add(new JsonCompactColumnizer()); - var result = ColumnizerPicker.DecideColumnizerByName(fileName, PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers); + [TestCase(@".\TestData\JsonColumnizerTest_01.txt", typeof(JsonCompactColumnizer))] + [TestCase(@".\TestData\SquareBracketColumnizerTest_02.txt", typeof(SquareBracketColumnizer))] + public void FindReplacementForAutoColumnizer_ValidTextFile_ReturnCorrectColumnizer( + string fileName, Type columnizerType) + { + var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName); + LogfileReader reader = new(path, new EncodingOptions(), true, 40, 50, new MultiFileOptions(), PluginRegistry.PluginRegistry.Instance); + reader.ReadFiles(); - Assert.That(columnizerType, Is.EqualTo(result.GetType())); - } + Mock autoColumnizer = new(); + autoColumnizer.Setup(a => a.GetName()).Returns("Auto Columnizer"); - [TestCase(@"Invalid Name", typeof(DefaultLogfileColumnizer))] - [TestCase(@"JSON Columnizer", typeof(JsonColumnizer.JsonColumnizer))] - public void DecideColumnizerByName_ValidTextFile_ReturnCorrectColumnizer( - string columnizerName, Type columnizerType) - { - string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, columnizerName); + // TODO: When DI container is ready, we can mock this set up. + PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers.Add(new JsonCompactColumnizer()); + var result = ColumnizerPicker.FindReplacementForAutoColumnizer(fileName, reader, autoColumnizer.Object, PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers); - // TODO: When DI container is ready, we can mock this set up. - PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers.Add(new JsonColumnizer.JsonColumnizer()); + Assert.That(columnizerType, Is.EqualTo(result.GetType())); + } - var result = ColumnizerPicker.DecideColumnizerByName(columnizerName, PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers); + [TestCase(@".\TestData\FileNotExists.txt", typeof(DefaultLogfileColumnizer))] + public void DecideColumnizerByName_WhenReaderIsNotReady_ReturnCorrectColumnizer( + string fileName, Type columnizerType) + { + var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName); - Assert.That(columnizerType, Is.EqualTo(result.GetType())); - } + // TODO: When DI container is ready, we can mock this set up. + PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers.Add(new JsonCompactColumnizer()); + var result = ColumnizerPicker.DecideColumnizerByName(fileName, PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers); - private class TestLogLine : ILogLine - { - public string Text => FullLine; - public string FullLine { get; set; } - public int LineNumber { get; set; } - } + Assert.That(columnizerType, Is.EqualTo(result.GetType())); + } + + [TestCase(@"Invalid Name", typeof(DefaultLogfileColumnizer))] + [TestCase(@"JSON Columnizer", typeof(JsonColumnizer.JsonColumnizer))] + public void DecideColumnizerByName_ValidTextFile_ReturnCorrectColumnizer( + string columnizerName, Type columnizerType) + { + var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, columnizerName); + + // TODO: When DI container is ready, we can mock this set up. + PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers.Add(new JsonColumnizer.JsonColumnizer()); + + var result = ColumnizerPicker.DecideColumnizerByName(columnizerName, PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers); + + Assert.That(columnizerType, Is.EqualTo(result.GetType())); + } + + private class TestLogLine : ILogLine + { + public string Text => FullLine; + public string FullLine { get; set; } + public int LineNumber { get; set; } } } \ No newline at end of file diff --git a/src/LogExpert.Tests/DateFormatParserTest.cs b/src/LogExpert.Tests/DateFormatParserTest.cs index 3bbe1af2..ca8622ee 100644 --- a/src/LogExpert.Tests/DateFormatParserTest.cs +++ b/src/LogExpert.Tests/DateFormatParserTest.cs @@ -8,121 +8,120 @@ using System.Linq; using System.Text; -namespace LogExpert.Tests +namespace LogExpert.Tests; + +[TestFixture] +public class DateFormatParserTest { - [TestFixture] - public class DateFormatParserTest + [Test] + public void CanParseAllCultures() { - [Test] - public void CanParseAllCultures() - { - var cultures = CultureInfo.GetCultures(CultureTypes.AllCultures); + var cultures = CultureInfo.GetCultures(CultureTypes.AllCultures); - // HashSet exclude = ["dz", "ckb-IR", "ar-SA", "lrc" , "lrc-IR", "mzn" , "mzn-IR", "ps"]; + // HashSet exclude = ["dz", "ckb-IR", "ar-SA", "lrc" , "lrc-IR", "mzn" , "mzn-IR", "ps"]; - foreach (var culture in cultures) + foreach (var culture in cultures) + { + if (culture.Name == "dz" || culture.Name == "ar" || culture.Name.StartsWith("ar-") || culture.Name.StartsWith("dz-")) { - if (culture.Name == "dz" || culture.Name == "ar" || culture.Name.StartsWith("ar-") || culture.Name.StartsWith("dz-")) - { - Console.WriteLine($"The ${culture.Name} (${culture.DisplayName}) time format is not supported yet."); - continue; - } + Console.WriteLine($"The ${culture.Name} (${culture.DisplayName}) time format is not supported yet."); + continue; + } - var datePattern = GetDateAndTimeFormat(culture); + var datePattern = GetDateAndTimeFormat(culture); - if (datePattern.StartsWith('g')) - { - Console.WriteLine("time format that starts with g is not supported yet."); - continue; - } + if (datePattern.StartsWith('g')) + { + Console.WriteLine("time format that starts with g is not supported yet."); + continue; + } - var message = $"Culture: {culture.Name} ({culture.EnglishName} {datePattern})"; - var sections = Parser.ParseSections(datePattern, out bool syntaxError); + var message = $"Culture: {culture.Name} ({culture.EnglishName} {datePattern})"; + var sections = Parser.ParseSections(datePattern, out var syntaxError); - Assert.That(syntaxError, Is.False, message); + Assert.That(syntaxError, Is.False, message); - var dateSection = sections.FirstOrDefault(); - Assert.That(dateSection, Is.Not.Null, message); + var dateSection = sections.FirstOrDefault(); + Assert.That(dateSection, Is.Not.Null, message); - var now = DateTime.Now; - var expectedFormattedDate = now.ToString(datePattern); - var actualFormattedDate = now.ToString(string.Join("", dateSection.GeneralTextDateDurationParts)); - Assert.That(actualFormattedDate, Is.EqualTo(expectedFormattedDate), message); - } + var now = DateTime.Now; + var expectedFormattedDate = now.ToString(datePattern); + var actualFormattedDate = now.ToString(string.Join("", dateSection.GeneralTextDateDurationParts)); + Assert.That(actualFormattedDate, Is.EqualTo(expectedFormattedDate), message); } + } - [Test] - [TestCase("en-US", "MM", "dd", "yyyy", "hh", "mm", "ss", "tt")] - [TestCase("fr-FR", "dd", "MM", "yyyy", "HH", "mm", "ss")] - [TestCase("de-DE", "dd", "MM", "yyyy", "HH", "mm", "ss")] - [TestCase("ar-TN", "dd", "MM", "yyyy", "hh", "mm", "ss", "tt")] - [TestCase("as", "dd", "MM", "yyyy", "tt", "hh", "mm", "ss")] - [TestCase("bg", "dd", "MM", "yyyy", "HH", "mm", "ss")] - public void TestDateFormatParserFromCulture(string cultureInfoName, params string[] expectedDateParts) - { - var culture = CultureInfo.GetCultureInfo(cultureInfoName); + [Test] + [TestCase("en-US", "MM", "dd", "yyyy", "hh", "mm", "ss", "tt")] + [TestCase("fr-FR", "dd", "MM", "yyyy", "HH", "mm", "ss")] + [TestCase("de-DE", "dd", "MM", "yyyy", "HH", "mm", "ss")] + [TestCase("ar-TN", "dd", "MM", "yyyy", "hh", "mm", "ss", "tt")] + [TestCase("as", "dd", "MM", "yyyy", "tt", "hh", "mm", "ss")] + [TestCase("bg", "dd", "MM", "yyyy", "HH", "mm", "ss")] + public void TestDateFormatParserFromCulture(string cultureInfoName, params string[] expectedDateParts) + { + var culture = CultureInfo.GetCultureInfo(cultureInfoName); - var datePattern = GetDateAndTimeFormat(culture); + var datePattern = GetDateAndTimeFormat(culture); - var sections = Parser.ParseSections(datePattern, out bool syntaxError); + var sections = Parser.ParseSections(datePattern, out var syntaxError); - var message = $"Culture: {culture.EnglishName}, Actual date pattern: {datePattern}"; + var message = $"Culture: {culture.EnglishName}, Actual date pattern: {datePattern}"; - Assert.That(syntaxError, Is.False, message); + Assert.That(syntaxError, Is.False, message); - var dateSection = sections.FirstOrDefault(); - Assert.That(dateSection, Is.Not.Null); + var dateSection = sections.FirstOrDefault(); + Assert.That(dateSection, Is.Not.Null); - var dateParts = dateSection - .GeneralTextDateDurationParts - .Where(Token.IsDatePart) - .Select(p => DateFormatPartAdjuster.AdjustDateTimeFormatPart(p)) - .ToArray(); + var dateParts = dateSection + .GeneralTextDateDurationParts + .Where(Token.IsDatePart) + .Select(p => DateFormatPartAdjuster.AdjustDateTimeFormatPart(p)) + .ToArray(); - Assert.That(dateParts.Length, Is.EqualTo(expectedDateParts.Length), message); + Assert.That(dateParts.Length, Is.EqualTo(expectedDateParts.Length), message); - for (var i = 0; i < expectedDateParts.Length; i++) - { - var expected = expectedDateParts[i]; - var actual = dateParts[i]; - Assert.That(actual, Is.EqualTo(expected), message); - } + for (var i = 0; i < expectedDateParts.Length; i++) + { + var expected = expectedDateParts[i]; + var actual = dateParts[i]; + Assert.That(actual, Is.EqualTo(expected), message); } + } - static string RemoveCharacters(string input, string charsToRemove) - { - HashSet charsToRemoveSet = new(charsToRemove); - StringBuilder result = new(); + static string RemoveCharacters(string input, string charsToRemove) + { + HashSet charsToRemoveSet = new(charsToRemove); + StringBuilder result = new(); - foreach (char c in input) + foreach (var c in input) + { + if (!charsToRemoveSet.Contains(c)) { - if (!charsToRemoveSet.Contains(c)) - { - result.Append(c); - } + result.Append(c); } - - return result.ToString(); } - private string GetDateAndTimeFormat(CultureInfo culture) - { + return result.ToString(); + } - string InvisibleUNICODEmarkers = - "\u00AD\u034F\u061C\u115F\u1160\u17B4\u17B5" + - "\u180B\u180C\u180D\u180E\u200B\u200C\u200D\u200E\u200F" + - "\u202A\u202B\u202C\u202D\u202E\u202F\u205F\u2060\u2062" + - "\u2063\u2064\u2066\u2067\u2068\u2069\u2800\u3164\uFE00" + - "\uFE01\uFE02\uFE03\uFE04\uFE05\uFE06\uFE07\uFE08\uFE09" + - "\uFE0A\uFE0B\uFE0C\uFE0D\uFE0E\uFE0F"; + private string GetDateAndTimeFormat(CultureInfo culture) + { + var InvisibleUNICODEmarkers = + "\u00AD\u034F\u061C\u115F\u1160\u17B4\u17B5" + + "\u180B\u180C\u180D\u180E\u200B\u200C\u200D\u200E\u200F" + + "\u202A\u202B\u202C\u202D\u202E\u202F\u205F\u2060\u2062" + + "\u2063\u2064\u2066\u2067\u2068\u2069\u2800\u3164\uFE00" + + "\uFE01\uFE02\uFE03\uFE04\uFE05\uFE06\uFE07\uFE08\uFE09" + + "\uFE0A\uFE0B\uFE0C\uFE0D\uFE0E\uFE0F"; - string dateTime = string.Concat(culture.DateTimeFormat.ShortDatePattern.ToString(), - " ", - culture.DateTimeFormat.LongTimePattern.ToString()); - return RemoveCharacters(dateTime, InvisibleUNICODEmarkers); + var dateTime = string.Concat(culture.DateTimeFormat.ShortDatePattern.ToString(), + " ", + culture.DateTimeFormat.LongTimePattern.ToString()); + + return RemoveCharacters(dateTime, InvisibleUNICODEmarkers); - } } } diff --git a/src/LogExpert.Tests/Extensions/EnumerableTests.cs b/src/LogExpert.Tests/Extensions/EnumerableTests.cs index 2c7548c1..cbc4fd7d 100644 --- a/src/LogExpert.Tests/Extensions/EnumerableTests.cs +++ b/src/LogExpert.Tests/Extensions/EnumerableTests.cs @@ -4,57 +4,56 @@ using System.Collections.Generic; -namespace LogExpert.Tests.Extensions +namespace LogExpert.Tests.Extensions; + +[TestFixture] +public class EnumerableTests { - [TestFixture] - public class EnumerableTests + [Test] + public void Extensions_IsEmpty_NullArray() { - [Test] - public void Extensions_IsEmpty_NullArray() - { - object[] arrayObject = null; + object[] arrayObject = null; - Assert.That(arrayObject.IsEmpty(), Is.True); - } + Assert.That(arrayObject.IsEmpty(), Is.True); + } - [Test] - public void Extensions_IsEmpty_EmptyArray() - { - object[] arrayObject = []; + [Test] + public void Extensions_IsEmpty_EmptyArray() + { + object[] arrayObject = []; - Assert.That(arrayObject.IsEmpty(), Is.True); - } + Assert.That(arrayObject.IsEmpty(), Is.True); + } - [Test] - public void Extensions_IsEmpty_FilledArray() - { - object[] arrayObject = [new()]; + [Test] + public void Extensions_IsEmpty_FilledArray() + { + object[] arrayObject = [new()]; - Assert.That(!arrayObject.IsEmpty(), Is.True); - } + Assert.That(!arrayObject.IsEmpty(), Is.True); + } - [Test] - public void Extensions_IsEmpty_NullIEnumerable() - { - IEnumerable arrayObject = null; + [Test] + public void Extensions_IsEmpty_NullIEnumerable() + { + IEnumerable arrayObject = null; - Assert.That(arrayObject.IsEmpty(), Is.True); - } + Assert.That(arrayObject.IsEmpty(), Is.True); + } - [Test] - public void Extensions_IsEmpty_EmptyIEnumerable() - { - IEnumerable arrayObject = []; + [Test] + public void Extensions_IsEmpty_EmptyIEnumerable() + { + IEnumerable arrayObject = []; - Assert.That(arrayObject.IsEmpty(), Is.True); - } + Assert.That(arrayObject.IsEmpty(), Is.True); + } - [Test] - public void Extensions_IsEmpty_FilledIEnumerable() - { - IEnumerable arrayObject = new List([new object()]); + [Test] + public void Extensions_IsEmpty_FilledIEnumerable() + { + IEnumerable arrayObject = new List([new object()]); - Assert.That(!arrayObject.IsEmpty(), Is.True); - } + Assert.That(!arrayObject.IsEmpty(), Is.True); } } diff --git a/src/LogExpert.Tests/JSONSaveTest.cs b/src/LogExpert.Tests/JSONSaveTest.cs index 35b4834c..e4193294 100644 --- a/src/LogExpert.Tests/JSONSaveTest.cs +++ b/src/LogExpert.Tests/JSONSaveTest.cs @@ -7,39 +7,38 @@ using System.IO; -namespace LogExpert.Tests +namespace LogExpert.Tests; + +[TestFixture] +public class JSONSaveTest { - [TestFixture] - public class JSONSaveTest + [Test(Author = "Hirogen", Description = "Save Options as JSON and Check if the written file can be cast again into the settings object")] + public void SaveOptionsAsJSON() { - [Test(Author = "Hirogen", Description = "Save Options as JSON and Check if the written file can be cast again into the settings object")] - public void SaveOptionsAsJSON() + ConfigManager.Instance.Settings.alwaysOnTop = true; + ConfigManager.Instance.Save(SettingsFlags.All); + var configDir = ConfigManager.Instance.ConfigDir; + var settingsFile = configDir + "\\settings.json"; + + Settings settings = null; + + Assert.DoesNotThrow(CastSettings); + Assert.That(settings, Is.Not.Null); + Assert.That(settings.alwaysOnTop, Is.True); + + ConfigManager.Instance.Settings.alwaysOnTop = false; + ConfigManager.Instance.Save(SettingsFlags.All); + + settings = null; + Assert.DoesNotThrow(CastSettings); + + Assert.That(settings, !Is.Null); + Assert.That(settings.alwaysOnTop, Is.False); + + + void CastSettings() { - ConfigManager.Instance.Settings.alwaysOnTop = true; - ConfigManager.Instance.Save(SettingsFlags.All); - string configDir = ConfigManager.Instance.ConfigDir; - string settingsFile = configDir + "\\settings.json"; - - Settings settings = null; - - Assert.DoesNotThrow(CastSettings); - Assert.That(settings, Is.Not.Null); - Assert.That(settings.alwaysOnTop, Is.True); - - ConfigManager.Instance.Settings.alwaysOnTop = false; - ConfigManager.Instance.Save(SettingsFlags.All); - - settings = null; - Assert.DoesNotThrow(CastSettings); - - Assert.That(settings, !Is.Null); - Assert.That(settings.alwaysOnTop, Is.False); - - - void CastSettings() - { - settings = JsonConvert.DeserializeObject(File.ReadAllText(settingsFile)); - } + settings = JsonConvert.DeserializeObject(File.ReadAllText(settingsFile)); } } } diff --git a/src/LogExpert.Tests/JsonColumnizerTest.cs b/src/LogExpert.Tests/JsonColumnizerTest.cs index 72a85d60..87e5c369 100644 --- a/src/LogExpert.Tests/JsonColumnizerTest.cs +++ b/src/LogExpert.Tests/JsonColumnizerTest.cs @@ -6,34 +6,33 @@ using System; using System.IO; -namespace LogExpert.Tests +namespace LogExpert.Tests; + +[TestFixture] +public class JsonColumnizerTest { - [TestFixture] - public class JsonColumnizerTest + [TestCase(@".\TestData\JsonColumnizerTest_01.txt", "time @m level")] + public void GetColumnNames_HappyFile_ColumnNameMatches(string fileName, string expectedHeaders) { - [TestCase(@".\TestData\JsonColumnizerTest_01.txt", "time @m level")] - public void GetColumnNames_HappyFile_ColumnNameMatches(string fileName, string expectedHeaders) - { - var jsonColumnizer = new JsonColumnizer.JsonColumnizer(); - string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName); - LogfileReader reader = new(path, new EncodingOptions(), true, 40, 50, new MultiFileOptions(), PluginRegistry.PluginRegistry.Instance); - reader.ReadFiles(); + var jsonColumnizer = new JsonColumnizer.JsonColumnizer(); + var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName); + LogfileReader reader = new(path, new EncodingOptions(), true, 40, 50, new MultiFileOptions(), PluginRegistry.PluginRegistry.Instance); + reader.ReadFiles(); - ILogLine line = reader.GetLogLine(0); - if (line != null) - { - jsonColumnizer.SplitLine(null, line); - } - - line = reader.GetLogLine(1); - if (line != null) - { - jsonColumnizer.SplitLine(null, line); - } + ILogLine line = reader.GetLogLine(0); + if (line != null) + { + jsonColumnizer.SplitLine(null, line); + } - var columnHeaders = jsonColumnizer.GetColumnNames(); - var result = string.Join(" ", columnHeaders); - Assert.That(expectedHeaders, Is.EqualTo(result)); + line = reader.GetLogLine(1); + if (line != null) + { + jsonColumnizer.SplitLine(null, line); } + + var columnHeaders = jsonColumnizer.GetColumnNames(); + var result = string.Join(" ", columnHeaders); + Assert.That(expectedHeaders, Is.EqualTo(result)); } } diff --git a/src/LogExpert.Tests/JsonCompactColumnizerTest.cs b/src/LogExpert.Tests/JsonCompactColumnizerTest.cs index 73e49d09..5811be64 100644 --- a/src/LogExpert.Tests/JsonCompactColumnizerTest.cs +++ b/src/LogExpert.Tests/JsonCompactColumnizerTest.cs @@ -7,38 +7,37 @@ using System.Collections.Generic; using System.IO; -namespace LogExpert.Tests +namespace LogExpert.Tests; + +[TestFixture] +public class JsonCompactColumnizerTest { - [TestFixture] - public class JsonCompactColumnizerTest + [TestCase(@".\TestData\JsonCompactColumnizerTest_01.json", Priority.PerfectlySupport)] + // As long as the json file contains one of the pre-defined key, it's perfectly supported. + [TestCase(@".\TestData\JsonCompactColumnizerTest_02.json", Priority.PerfectlySupport)] + [TestCase(@".\TestData\JsonCompactColumnizerTest_03.json", Priority.WellSupport)] + public void GetPriority_HappyFile_PriorityMatches(string fileName, Priority priority) { - [TestCase(@".\TestData\JsonCompactColumnizerTest_01.json", Priority.PerfectlySupport)] - // As long as the json file contains one of the pre-defined key, it's perfectly supported. - [TestCase(@".\TestData\JsonCompactColumnizerTest_02.json", Priority.PerfectlySupport)] - [TestCase(@".\TestData\JsonCompactColumnizerTest_03.json", Priority.WellSupport)] - public void GetPriority_HappyFile_PriorityMatches(string fileName, Priority priority) + var jsonCompactColumnizer = new JsonColumnizer.JsonCompactColumnizer(); + var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName); + LogfileReader logFileReader = new(path, new EncodingOptions(), true, 40, 50, new MultiFileOptions(), PluginRegistry.PluginRegistry.Instance); + logFileReader.ReadFiles(); + List loglines = new() { - var jsonCompactColumnizer = new JsonColumnizer.JsonCompactColumnizer(); - string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName); - LogfileReader logFileReader = new(path, new EncodingOptions(), true, 40, 50, new MultiFileOptions(), PluginRegistry.PluginRegistry.Instance); - logFileReader.ReadFiles(); - List loglines = new() - { - // Sampling a few lines to select the correct columnizer - logFileReader.GetLogLine(0), - logFileReader.GetLogLine(1), - logFileReader.GetLogLine(2), - logFileReader.GetLogLine(3), - logFileReader.GetLogLine(4), - logFileReader.GetLogLine(5), - logFileReader.GetLogLine(25), - logFileReader.GetLogLine(100), - logFileReader.GetLogLine(200), - logFileReader.GetLogLine(400) - }; + // Sampling a few lines to select the correct columnizer + logFileReader.GetLogLine(0), + logFileReader.GetLogLine(1), + logFileReader.GetLogLine(2), + logFileReader.GetLogLine(3), + logFileReader.GetLogLine(4), + logFileReader.GetLogLine(5), + logFileReader.GetLogLine(25), + logFileReader.GetLogLine(100), + logFileReader.GetLogLine(200), + logFileReader.GetLogLine(400) + }; - var result = jsonCompactColumnizer.GetPriority(path, loglines); - Assert.That(result, Is.EqualTo(priority)); - } + var result = jsonCompactColumnizer.GetPriority(path, loglines); + Assert.That(result, Is.EqualTo(priority)); } } diff --git a/src/LogExpert.Tests/LocalFileSystemTest.cs b/src/LogExpert.Tests/LocalFileSystemTest.cs index ab765ef3..76a6ee1a 100644 --- a/src/LogExpert.Tests/LocalFileSystemTest.cs +++ b/src/LogExpert.Tests/LocalFileSystemTest.cs @@ -5,50 +5,49 @@ using System; using System.IO; -namespace LogExpert.Tests +namespace LogExpert.Tests; + +[TestFixture] +internal class LocalFileSystemTest : RolloverHandlerTestBase { - [TestFixture] - internal class LocalFileSystemTest : RolloverHandlerTestBase + [TearDown] + public void TearDown() + { + Cleanup(); + } + + [OneTimeSetUp] + public void Boot() + { + Cleanup(); + } + + + [Test] + public void TestUriHandle() + { + LocalFileSystem fs = new(); + Assert.That(fs.CanHandleUri("file:///c:/logfile.txt"), Is.True); + Assert.That(fs.CanHandleUri("file:///c:\\logfile.txt"), Is.True); + Assert.That(fs.CanHandleUri("c:/logfile.txt"), Is.True); + Assert.That(fs.CanHandleUri("c:\\logfile.txt"), Is.True); + } + + [Test] + public void TestUriToFileStream() { - [TearDown] - public void TearDown() - { - Cleanup(); - } - - [OneTimeSetUp] - public void Boot() - { - Cleanup(); - } - - - [Test] - public void TestUriHandle() - { - LocalFileSystem fs = new(); - Assert.That(fs.CanHandleUri("file:///c:/logfile.txt"), Is.True); - Assert.That(fs.CanHandleUri("file:///c:\\logfile.txt"), Is.True); - Assert.That(fs.CanHandleUri("c:/logfile.txt"), Is.True); - Assert.That(fs.CanHandleUri("c:\\logfile.txt"), Is.True); - } - - [Test] - public void TestUriToFileStream() - { - DirectoryInfo dInfo = Directory.CreateDirectory(RolloverHandlerTest.TEST_DIR_NAME); - string fullName = CreateFile(dInfo, "test.log"); - - LocalFileSystem fs = new(); - ILogFileInfo info = fs.GetLogfileInfo(fullName); - Assert.That(info.Length > 0, Is.True); - Assert.That(info.OriginalLength == info.Length, Is.True); - Stream stream = info.OpenStream(); - Assert.That(stream.CanSeek, Is.True); - StreamReader reader = new(stream); - string line = reader.ReadLine(); - Assert.That(line.StartsWith("line number", StringComparison.InvariantCultureIgnoreCase), Is.True); - reader.Close(); - } + DirectoryInfo dInfo = Directory.CreateDirectory(RolloverHandlerTest.TEST_DIR_NAME); + var fullName = CreateFile(dInfo, "test.log"); + + LocalFileSystem fs = new(); + ILogFileInfo info = fs.GetLogfileInfo(fullName); + Assert.That(info.Length > 0, Is.True); + Assert.That(info.OriginalLength == info.Length, Is.True); + Stream stream = info.OpenStream(); + Assert.That(stream.CanSeek, Is.True); + StreamReader reader = new(stream); + var line = reader.ReadLine(); + Assert.That(line.StartsWith("line number", StringComparison.InvariantCultureIgnoreCase), Is.True); + reader.Close(); } } \ No newline at end of file diff --git a/src/LogExpert.Tests/LogStreamReaderTest.cs b/src/LogExpert.Tests/LogStreamReaderTest.cs index f7e0d6f0..4ee9dd35 100644 --- a/src/LogExpert.Tests/LogStreamReaderTest.cs +++ b/src/LogExpert.Tests/LogStreamReaderTest.cs @@ -6,26 +6,72 @@ using System.IO; using System.Text; -namespace LogExpert.Tests +namespace LogExpert.Tests; + +[TestFixture] +public class LogStreamReaderTest { - [TestFixture] - public class LogStreamReaderTest + [Test] + [TestCase("Line 1\nLine 2\nLine 3", 3)] + [TestCase("Line 1\nLine 2\nLine 3\n", 3)] + [TestCase("Line 1\r\nLine 2\r\nLine 3", 3)] + [TestCase("Line 1\r\nLine 2\r\nLine 3\r\n", 3)] + [TestCase("Line 1\rLine 2\rLine 3", 3)] + [TestCase("Line 1\rLine 2\rLine 3\r", 3)] + public void ReadLinesWithSystemNewLine(string text, int expectedLines) + { + using var stream = new MemoryStream(Encoding.ASCII.GetBytes(text)); + using var reader = new PositionAwareStreamReaderSystem(stream, new EncodingOptions()); + var lineCount = 0; + while (true) + { + var line = reader.ReadLine(); + if (line == null) + { + break; + } + + lineCount += 1; + + Assert.That(line.StartsWith($"Line {lineCount}"), $"Invalid line: {line}"); + } + + Assert.That(expectedLines, Is.EqualTo(lineCount), $"Unexpected lines:\n{text}"); + } + + [Test] + [TestCase("\n\n\n", 3)] + [TestCase("\r\n\r\n\r\n", 3)] + [TestCase("\r\r\r", 3)] + public void CountLinesWithSystemNewLine(string text, int expectedLines) + { + using var stream = new MemoryStream(Encoding.ASCII.GetBytes(text)); + using var reader = new PositionAwareStreamReaderSystem(stream, new EncodingOptions()); + var lineCount = 0; + while (reader.ReadLine() != null) + { + lineCount += 1; + } + + Assert.That(expectedLines, Is.EqualTo(lineCount), $"Unexpected lines:\n{text}"); + } + + [Test] + [TestCase("Line 1\nLine 2\nLine 3", 3)] + [TestCase("Line 1\nLine 2\nLine 3\n", 3)] + [TestCase("Line 1\r\nLine 2\r\nLine 3", 3)] + [TestCase("Line 1\r\nLine 2\r\nLine 3\r\n", 3)] + [TestCase("Line 1\rLine 2\rLine 3", 3)] + [TestCase("Line 1\rLine 2\rLine 3\r", 3)] + public void ReadLinesWithLegacyNewLine(string text, int expectedLines) { - [Test] - [TestCase("Line 1\nLine 2\nLine 3", 3)] - [TestCase("Line 1\nLine 2\nLine 3\n", 3)] - [TestCase("Line 1\r\nLine 2\r\nLine 3", 3)] - [TestCase("Line 1\r\nLine 2\r\nLine 3\r\n", 3)] - [TestCase("Line 1\rLine 2\rLine 3", 3)] - [TestCase("Line 1\rLine 2\rLine 3\r", 3)] - public void ReadLinesWithSystemNewLine(string text, int expectedLines) + using (var stream = new MemoryStream(Encoding.ASCII.GetBytes(text))) + using (var reader = new PositionAwareStreamReaderLegacy(stream, new EncodingOptions())) { - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(text)); - using var reader = new PositionAwareStreamReaderSystem(stream, new EncodingOptions()); - int lineCount = 0; + var lineCount = 0; while (true) { - string line = reader.ReadLine(); + var line = reader.ReadLine(); if (line == null) { break; @@ -38,71 +84,24 @@ public void ReadLinesWithSystemNewLine(string text, int expectedLines) Assert.That(expectedLines, Is.EqualTo(lineCount), $"Unexpected lines:\n{text}"); } - - [Test] - [TestCase("\n\n\n", 3)] - [TestCase("\r\n\r\n\r\n", 3)] - [TestCase("\r\r\r", 3)] - public void CountLinesWithSystemNewLine(string text, int expectedLines) + } + [Test] + [TestCase("\n\n\n", 3)] + [TestCase("\r\n\r\n\r\n", 3)] + [TestCase("\r\r\r", 3)] + public void CountLinesWithLegacyNewLine(string text, int expectedLines) + { + using (var stream = new MemoryStream(Encoding.ASCII.GetBytes(text))) + using (var reader = new PositionAwareStreamReaderLegacy(stream, new EncodingOptions())) { - using var stream = new MemoryStream(Encoding.ASCII.GetBytes(text)); - using var reader = new PositionAwareStreamReaderSystem(stream, new EncodingOptions()); - int lineCount = 0; + var lineCount = 0; while (reader.ReadLine() != null) { lineCount += 1; } - Assert.That(expectedLines, Is.EqualTo(lineCount), $"Unexpected lines:\n{text}"); - } - - [Test] - [TestCase("Line 1\nLine 2\nLine 3", 3)] - [TestCase("Line 1\nLine 2\nLine 3\n", 3)] - [TestCase("Line 1\r\nLine 2\r\nLine 3", 3)] - [TestCase("Line 1\r\nLine 2\r\nLine 3\r\n", 3)] - [TestCase("Line 1\rLine 2\rLine 3", 3)] - [TestCase("Line 1\rLine 2\rLine 3\r", 3)] - public void ReadLinesWithLegacyNewLine(string text, int expectedLines) - { - using (var stream = new MemoryStream(Encoding.ASCII.GetBytes(text))) - using (var reader = new PositionAwareStreamReaderLegacy(stream, new EncodingOptions())) - { - int lineCount = 0; - while (true) - { - string line = reader.ReadLine(); - if (line == null) - { - break; - } - - lineCount += 1; - Assert.That(line.StartsWith($"Line {lineCount}"), $"Invalid line: {line}"); - } - - Assert.That(expectedLines, Is.EqualTo(lineCount), $"Unexpected lines:\n{text}"); - } - } - [Test] - [TestCase("\n\n\n", 3)] - [TestCase("\r\n\r\n\r\n", 3)] - [TestCase("\r\r\r", 3)] - public void CountLinesWithLegacyNewLine(string text, int expectedLines) - { - using (var stream = new MemoryStream(Encoding.ASCII.GetBytes(text))) - using (var reader = new PositionAwareStreamReaderLegacy(stream, new EncodingOptions())) - { - int lineCount = 0; - while (reader.ReadLine() != null) - { - lineCount += 1; - } - - - Assert.That(expectedLines, Is.EqualTo(lineCount), $"Unexpected lines:\n{text}"); - } + Assert.That(expectedLines, Is.EqualTo(lineCount), $"Unexpected lines:\n{text}"); } } } diff --git a/src/LogExpert.Tests/LogWindowTest.cs b/src/LogExpert.Tests/LogWindowTest.cs index 6391bf0e..93880fc9 100644 --- a/src/LogExpert.Tests/LogWindowTest.cs +++ b/src/LogExpert.Tests/LogWindowTest.cs @@ -1,32 +1,31 @@ using NUnit.Framework; -namespace LogExpert.Tests +namespace LogExpert.Tests; + +//TODO Find out why there is a "Drag and Drop Exception" until then, this 2 Tests can not be executed the block the build pipeline +[TestFixture] +public class LogWindowTest { - //TODO Find out why there is a "Drag and Drop Exception" until then, this 2 Tests can not be executed the block the build pipeline - [TestFixture] - public class LogWindowTest - { - //// TODO: Add more tests when DI container is ready. - //[TestCase(@".\TestData\JsonColumnizerTest_01.txt", typeof(DefaultLogfileColumnizer))] - //public void Instantiate_JsonFile_BuildCorrectColumnizer(string fileName, Type columnizerType) - //{ - // LogTabWindow logTabWindow = new(null, 0, false); - // LogWindow logWindow = new(logTabWindow, fileName, false, false); + //// TODO: Add more tests when DI container is ready. + //[TestCase(@".\TestData\JsonColumnizerTest_01.txt", typeof(DefaultLogfileColumnizer))] + //public void Instantiate_JsonFile_BuildCorrectColumnizer(string fileName, Type columnizerType) + //{ + // LogTabWindow logTabWindow = new(null, 0, false); + // LogWindow logWindow = new(logTabWindow, fileName, false, false); - // Assert.That(columnizerType, Is.EqualTo(logWindow.CurrentColumnizer.GetType())); - //} + // Assert.That(columnizerType, Is.EqualTo(logWindow.CurrentColumnizer.GetType())); + //} - //[TestCase(@".\TestData\XmlTest_01.xml")] - //[TestCase(@".\TestData\CsvTest_01.csv")] - //public void Instantiate_AnyFile_NotCrash(string fileName) - //{ - // PluginRegistry.GetInstance().RegisteredColumnizers.Add(new Log4jXmlColumnizer()); - // PluginRegistry.GetInstance().RegisteredColumnizers.Add(new CsvColumnizerType()); + //[TestCase(@".\TestData\XmlTest_01.xml")] + //[TestCase(@".\TestData\CsvTest_01.csv")] + //public void Instantiate_AnyFile_NotCrash(string fileName) + //{ + // PluginRegistry.GetInstance().RegisteredColumnizers.Add(new Log4jXmlColumnizer()); + // PluginRegistry.GetInstance().RegisteredColumnizers.Add(new CsvColumnizerType()); - // LogTabWindow logTabWindow = new(null, 0, false); - // LogWindow logWindow = new(logTabWindow, fileName, false, false); + // LogTabWindow logTabWindow = new(null, 0, false); + // LogWindow logWindow = new(logTabWindow, fileName, false, false); - // Assert.That(true, Is.True); - //} - } + // Assert.That(true, Is.True); + //} } diff --git a/src/LogExpert.Tests/ReaderTest.cs b/src/LogExpert.Tests/ReaderTest.cs index 4e59a5bd..98367143 100644 --- a/src/LogExpert.Tests/ReaderTest.cs +++ b/src/LogExpert.Tests/ReaderTest.cs @@ -8,62 +8,61 @@ using System.IO; using System.Text; -namespace LogExpert.Tests +namespace LogExpert.Tests; + +[TestFixture] +internal class ReaderTest { - [TestFixture] - internal class ReaderTest + [TearDown] + public void TearDown() { - [TearDown] - public void TearDown() - { - } + } - [OneTimeSetUp] - public void Boot() - { - } + [OneTimeSetUp] + public void Boot() + { + } - private void CompareReaderImplementationsInternal(string fileName, Encoding enc, int maxPosition) - { - string path = Environment.CurrentDirectory + "\\data\\"; - EncodingOptions encOpts = new(); - encOpts.Encoding = enc; + private void CompareReaderImplementationsInternal(string fileName, Encoding enc, int maxPosition) + { + var path = Environment.CurrentDirectory + "\\data\\"; + EncodingOptions encOpts = new(); + encOpts.Encoding = enc; - using Stream s1 = new FileStream(path + fileName, FileMode.Open, FileAccess.Read); - using Stream s2 = new FileStream(path + fileName, FileMode.Open, FileAccess.Read); - using ILogStreamReader r1 = new PositionAwareStreamReaderLegacy(s1, encOpts); - using ILogStreamReader r2 = new PositionAwareStreamReaderSystem(s2, encOpts); - for (int lineNum = 0; ; lineNum++) + using Stream s1 = new FileStream(path + fileName, FileMode.Open, FileAccess.Read); + using Stream s2 = new FileStream(path + fileName, FileMode.Open, FileAccess.Read); + using ILogStreamReader r1 = new PositionAwareStreamReaderLegacy(s1, encOpts); + using ILogStreamReader r2 = new PositionAwareStreamReaderSystem(s2, encOpts); + for (var lineNum = 0; ; lineNum++) + { + var line1 = r1.ReadLine(); + var line2 = r2.ReadLine(); + if (line1 == null && line2 == null) { - string line1 = r1.ReadLine(); - string line2 = r2.ReadLine(); - if (line1 == null && line2 == null) - { - break; - } + break; + } - Assert.That(line1, Is.EqualTo(line2), "File " + fileName); + Assert.That(line1, Is.EqualTo(line2), "File " + fileName); - if (r1.Position != maxPosition) - { - Assert.That(r2.Position, Is.EqualTo(r1.Position), "Line " + lineNum + ", File: " + fileName); - } - else - { - //Its desired that the position of the new implementation is 2 bytes ahead to fix the problem of empty lines every time a new line is appended. - Assert.That(r2.Position - 2, Is.EqualTo(r1.Position), "Line " + lineNum + ", File: " + fileName); - } + if (r1.Position != maxPosition) + { + Assert.That(r2.Position, Is.EqualTo(r1.Position), "Line " + lineNum + ", File: " + fileName); + } + else + { + //Its desired that the position of the new implementation is 2 bytes ahead to fix the problem of empty lines every time a new line is appended. + Assert.That(r2.Position - 2, Is.EqualTo(r1.Position), "Line " + lineNum + ", File: " + fileName); } } - - //TODO find out why it does not work with appveyor, but works fine with normal environment! - //[Test] - //[TestCase("50 MB.txt", "Windows-1252", 50000000)] - //[TestCase("50 MB UTF16.txt", "Unicode", 49999998)] - //[TestCase("50 MB UTF8.txt", "UTF-8", 50000000)] - //public void CompareReaderImplementations(string fileName, string encoding, int maxPosition) - //{ - // CompareReaderImplementationsInternal(fileName, Encoding.GetEncoding(encoding), maxPosition); - //} } + + //TODO find out why it does not work with appveyor, but works fine with normal environment! + //[Test] + //[TestCase("50 MB.txt", "Windows-1252", 50000000)] + //[TestCase("50 MB UTF16.txt", "Unicode", 49999998)] + //[TestCase("50 MB UTF8.txt", "UTF-8", 50000000)] + //public void CompareReaderImplementations(string fileName, string encoding, int maxPosition) + //{ + // CompareReaderImplementationsInternal(fileName, Encoding.GetEncoding(encoding), maxPosition); + //} } \ No newline at end of file diff --git a/src/LogExpert.Tests/RollingNameTest.cs b/src/LogExpert.Tests/RollingNameTest.cs index 783bd2fa..a85f94b4 100644 --- a/src/LogExpert.Tests/RollingNameTest.cs +++ b/src/LogExpert.Tests/RollingNameTest.cs @@ -2,68 +2,67 @@ using NUnit.Framework; -namespace LogExpert.Tests +namespace LogExpert.Tests; + +[TestFixture] +internal class RollingNameTest { - [TestFixture] - internal class RollingNameTest + [Test] + [TestCase("engine_2010-06-12_0.log", "*$D(yyyy-MM-dd)_$I.log")] + [TestCase("engine_2010-06-12.log", "*$D(yyyy-MM-dd).log")] + [TestCase("engine_0.log", "*_$I.log")] + [TestCase("engine.log","*.log$J(.)")] + [TestCase("engine.log","engine$J.log")] + [TestCase("engine1.log","engine$J.log")] + [TestCase("engine.log", "*$J(.)")] + [TestCase("engine_2010-06-12.log", "*$D(yyyy-MM-dd).log$J(.)")] + public void TestFilename1(string expectedResult, string formatString) { - [Test] - [TestCase("engine_2010-06-12_0.log", "*$D(yyyy-MM-dd)_$I.log")] - [TestCase("engine_2010-06-12.log", "*$D(yyyy-MM-dd).log")] - [TestCase("engine_0.log", "*_$I.log")] - [TestCase("engine.log","*.log$J(.)")] - [TestCase("engine.log","engine$J.log")] - [TestCase("engine1.log","engine$J.log")] - [TestCase("engine.log", "*$J(.)")] - [TestCase("engine_2010-06-12.log", "*$D(yyyy-MM-dd).log$J(.)")] - public void TestFilename1(string expectedResult, string formatString) - { - RolloverFilenameBuilder fnb = new(formatString); - fnb.SetFileName(expectedResult); - string name = fnb.BuildFileName(); - Assert.That(name, Is.EqualTo(expectedResult)); - } + RolloverFilenameBuilder fnb = new(formatString); + fnb.SetFileName(expectedResult); + var name = fnb.BuildFileName(); + Assert.That(name, Is.EqualTo(expectedResult)); + } - [Test] - [TestCase("engine_2010-06-12_0.log", "engine_2010-06-12_1.log", "*$D(yyyy-MM-dd)_$I.log")] - [TestCase("engine_2010-06-12.log", "engine_2010-06-12.log", "*$D(yyyy-MM-dd).log")] - [TestCase("engine_0.log", "engine_1.log","*_$I.log")] - [TestCase("engine.log", "engine.log.1","*.log$J(.)")] - [TestCase("engine.log", "engine1.log","engine$J.log")] - [TestCase("engine1.log", "engine2.log","engine$J.log")] - [TestCase("engine.log", "engine.log.1","*$J(.)")] - [TestCase("engine_2010-06-12.log", "engine_2010-06-12.log.1", "*$D(yyyy-MM-dd).log$J(.)")] - public void TestFilenameAnd1(string fileName, string expectedResult, string formatString) - { - RolloverFilenameBuilder fnb = new(formatString); - fnb.SetFileName(fileName); - fnb.Index += 1; - string name = fnb.BuildFileName(); - Assert.That(name, Is.EqualTo(expectedResult)); - } + [Test] + [TestCase("engine_2010-06-12_0.log", "engine_2010-06-12_1.log", "*$D(yyyy-MM-dd)_$I.log")] + [TestCase("engine_2010-06-12.log", "engine_2010-06-12.log", "*$D(yyyy-MM-dd).log")] + [TestCase("engine_0.log", "engine_1.log","*_$I.log")] + [TestCase("engine.log", "engine.log.1","*.log$J(.)")] + [TestCase("engine.log", "engine1.log","engine$J.log")] + [TestCase("engine1.log", "engine2.log","engine$J.log")] + [TestCase("engine.log", "engine.log.1","*$J(.)")] + [TestCase("engine_2010-06-12.log", "engine_2010-06-12.log.1", "*$D(yyyy-MM-dd).log$J(.)")] + public void TestFilenameAnd1(string fileName, string expectedResult, string formatString) + { + RolloverFilenameBuilder fnb = new(formatString); + fnb.SetFileName(fileName); + fnb.Index += 1; + var name = fnb.BuildFileName(); + Assert.That(name, Is.EqualTo(expectedResult)); + } - [Test] - [TestCase("engine.log", "engine.log.2","*$J(.)")] - [TestCase("engine.log", "engine.log.2","*.log$J(.)")] - public void TestFilenameAnd2(string fileName, string expectedResult, string formatString) - { - RolloverFilenameBuilder fnb = new(formatString); - fnb.SetFileName(fileName); - fnb.Index += 2; - string name = fnb.BuildFileName(); - Assert.That(name, Is.EqualTo(expectedResult)); - } + [Test] + [TestCase("engine.log", "engine.log.2","*$J(.)")] + [TestCase("engine.log", "engine.log.2","*.log$J(.)")] + public void TestFilenameAnd2(string fileName, string expectedResult, string formatString) + { + RolloverFilenameBuilder fnb = new(formatString); + fnb.SetFileName(fileName); + fnb.Index += 2; + var name = fnb.BuildFileName(); + Assert.That(name, Is.EqualTo(expectedResult)); + } - [Test] - [TestCase("engine1.log", "engine.log","engine$J.log")] - public void TestFilenameMinus1(string fileName, string expectedResult, string formatString) - { - RolloverFilenameBuilder fnb = new(formatString); - fnb.SetFileName(fileName); - fnb.Index -= 1; - string name = fnb.BuildFileName(); - Assert.That(name, Is.EqualTo("engine.log")); - } + [Test] + [TestCase("engine1.log", "engine.log","engine$J.log")] + public void TestFilenameMinus1(string fileName, string expectedResult, string formatString) + { + RolloverFilenameBuilder fnb = new(formatString); + fnb.SetFileName(fileName); + fnb.Index -= 1; + var name = fnb.BuildFileName(); + Assert.That(name, Is.EqualTo("engine.log")); } } \ No newline at end of file diff --git a/src/LogExpert.Tests/RolloverHandlerTest.cs b/src/LogExpert.Tests/RolloverHandlerTest.cs index 9c4e7557..f93e4045 100644 --- a/src/LogExpert.Tests/RolloverHandlerTest.cs +++ b/src/LogExpert.Tests/RolloverHandlerTest.cs @@ -7,51 +7,50 @@ using System; using System.Collections.Generic; -namespace LogExpert.Tests +namespace LogExpert.Tests; + +[TestFixture] +internal class RolloverHandlerTest : RolloverHandlerTestBase { - [TestFixture] - internal class RolloverHandlerTest : RolloverHandlerTestBase + [Test] + [TestCase("*$J(.)", 66)] + public void TestFilenameListWithAppendedIndex(string format, int retries) { - [Test] - [TestCase("*$J(.)", 66)] - public void TestFilenameListWithAppendedIndex(string format, int retries) - { - MultiFileOptions options = new(); - options.FormatPattern = format; - options.MaxDayTry = retries; + MultiFileOptions options = new(); + options.FormatPattern = format; + options.MaxDayTry = retries; - LinkedList files = CreateTestFilesWithoutDate(); + LinkedList files = CreateTestFilesWithoutDate(); - string firstFile = files.Last.Value; + var firstFile = files.Last.Value; - ILogFileInfo info = new LogFileInfo(new Uri(firstFile)); - RolloverFilenameHandler handler = new(info, options); - LinkedList fileList = handler.GetNameList(PluginRegistry.PluginRegistry.Instance); + ILogFileInfo info = new LogFileInfo(new Uri(firstFile)); + RolloverFilenameHandler handler = new(info, options); + LinkedList fileList = handler.GetNameList(PluginRegistry.PluginRegistry.Instance); - Assert.That(fileList, Is.EqualTo(files)); + Assert.That(fileList, Is.EqualTo(files)); - Cleanup(); - } + Cleanup(); + } - [Test] - [TestCase("*$D(YYYY-mm-DD)_$I.log", 3)] - public void TestFilenameListWithDate(string format, int retries) - { - MultiFileOptions options = new(); - options.FormatPattern = format; - options.MaxDayTry = retries; + [Test] + [TestCase("*$D(YYYY-mm-DD)_$I.log", 3)] + public void TestFilenameListWithDate(string format, int retries) + { + MultiFileOptions options = new(); + options.FormatPattern = format; + options.MaxDayTry = retries; - LinkedList files = CreateTestFilesWithDate(); + LinkedList files = CreateTestFilesWithDate(); - string firstFile = files.Last.Value; + var firstFile = files.Last.Value; - ILogFileInfo info = new LogFileInfo(new Uri(firstFile)); - RolloverFilenameHandler handler = new(info, options); - LinkedList fileList = handler.GetNameList(PluginRegistry.PluginRegistry.Instance); + ILogFileInfo info = new LogFileInfo(new Uri(firstFile)); + RolloverFilenameHandler handler = new(info, options); + LinkedList fileList = handler.GetNameList(PluginRegistry.PluginRegistry.Instance); - Assert.That(fileList, Is.EqualTo(files)); + Assert.That(fileList, Is.EqualTo(files)); - Cleanup(); - } + Cleanup(); } } \ No newline at end of file diff --git a/src/LogExpert.Tests/RolloverHandlerTestBase.cs b/src/LogExpert.Tests/RolloverHandlerTestBase.cs index 06617bf0..ea84c2cd 100644 --- a/src/LogExpert.Tests/RolloverHandlerTestBase.cs +++ b/src/LogExpert.Tests/RolloverHandlerTestBase.cs @@ -4,105 +4,104 @@ using System.Collections.Generic; using System.IO; -namespace LogExpert.Tests +namespace LogExpert.Tests; + +internal class RolloverHandlerTestBase { - internal class RolloverHandlerTestBase - { - #region Fields + #region Fields - public const string TEST_DIR_NAME = "test"; - public DirectoryInfo testDirectory; + public const string TEST_DIR_NAME = "test"; + public DirectoryInfo testDirectory; - #endregion + #endregion - protected LinkedList CreateTestFilesWithDate() - { - LinkedList createdFiles = new(); - DirectoryInfo dInfo = Directory.CreateDirectory(TEST_DIR_NAME); - testDirectory = dInfo; - createdFiles.AddLast(CreateFile(dInfo, "engine_2010-06-08_1.log")); - createdFiles.AddLast(CreateFile(dInfo, "engine_2010-06-08_0.log")); - createdFiles.AddLast(CreateFile(dInfo, "engine_2010-06-10_0.log")); - createdFiles.AddLast(CreateFile(dInfo, "engine_2010-06-11_1.log")); - createdFiles.AddLast(CreateFile(dInfo, "engine_2010-06-11_0.log")); - createdFiles.AddLast(CreateFile(dInfo, "engine_2010-06-12_2.log")); - createdFiles.AddLast(CreateFile(dInfo, "engine_2010-06-12_1.log")); - createdFiles.AddLast(CreateFile(dInfo, "engine_2010-06-12_0.log")); - return createdFiles; - } + protected LinkedList CreateTestFilesWithDate() + { + LinkedList createdFiles = new(); + DirectoryInfo dInfo = Directory.CreateDirectory(TEST_DIR_NAME); + testDirectory = dInfo; + createdFiles.AddLast(CreateFile(dInfo, "engine_2010-06-08_1.log")); + createdFiles.AddLast(CreateFile(dInfo, "engine_2010-06-08_0.log")); + createdFiles.AddLast(CreateFile(dInfo, "engine_2010-06-10_0.log")); + createdFiles.AddLast(CreateFile(dInfo, "engine_2010-06-11_1.log")); + createdFiles.AddLast(CreateFile(dInfo, "engine_2010-06-11_0.log")); + createdFiles.AddLast(CreateFile(dInfo, "engine_2010-06-12_2.log")); + createdFiles.AddLast(CreateFile(dInfo, "engine_2010-06-12_1.log")); + createdFiles.AddLast(CreateFile(dInfo, "engine_2010-06-12_0.log")); + return createdFiles; + } - protected LinkedList CreateTestFilesWithoutDate() - { - LinkedList createdFiles = new(); - DirectoryInfo dInfo = Directory.CreateDirectory(TEST_DIR_NAME); - testDirectory = dInfo; - createdFiles.AddLast(CreateFile(dInfo, "engine.log.6")); - createdFiles.AddLast(CreateFile(dInfo, "engine.log.5")); - createdFiles.AddLast(CreateFile(dInfo, "engine.log.4")); - createdFiles.AddLast(CreateFile(dInfo, "engine.log.3")); - createdFiles.AddLast(CreateFile(dInfo, "engine.log.2")); - createdFiles.AddLast(CreateFile(dInfo, "engine.log.1")); - createdFiles.AddLast(CreateFile(dInfo, "engine.log")); - return createdFiles; - } + protected LinkedList CreateTestFilesWithoutDate() + { + LinkedList createdFiles = new(); + DirectoryInfo dInfo = Directory.CreateDirectory(TEST_DIR_NAME); + testDirectory = dInfo; + createdFiles.AddLast(CreateFile(dInfo, "engine.log.6")); + createdFiles.AddLast(CreateFile(dInfo, "engine.log.5")); + createdFiles.AddLast(CreateFile(dInfo, "engine.log.4")); + createdFiles.AddLast(CreateFile(dInfo, "engine.log.3")); + createdFiles.AddLast(CreateFile(dInfo, "engine.log.2")); + createdFiles.AddLast(CreateFile(dInfo, "engine.log.1")); + createdFiles.AddLast(CreateFile(dInfo, "engine.log")); + return createdFiles; + } - protected LinkedList RolloverSimulation(LinkedList files, string formatPattern, - bool deleteLatestFile) + protected LinkedList RolloverSimulation(LinkedList files, string formatPattern, + bool deleteLatestFile) + { + LinkedList fileList = files; + RolloverFilenameBuilder fnb = new(formatPattern); + fnb.SetFileName(fileList.Last.Value); + fnb.Index += fileList.Count; + var newFileName = fnb.BuildFileName(); + fileList.AddFirst(newFileName); + LinkedList.Enumerator enumerator = fileList.GetEnumerator(); + LinkedList.Enumerator nextEnumerator = fileList.GetEnumerator(); + nextEnumerator.MoveNext(); // move on 2nd entry + enumerator.MoveNext(); + while (nextEnumerator.MoveNext()) { - LinkedList fileList = files; - RolloverFilenameBuilder fnb = new(formatPattern); - fnb.SetFileName(fileList.Last.Value); - fnb.Index += fileList.Count; - string newFileName = fnb.BuildFileName(); - fileList.AddFirst(newFileName); - LinkedList.Enumerator enumerator = fileList.GetEnumerator(); - LinkedList.Enumerator nextEnumerator = fileList.GetEnumerator(); - nextEnumerator.MoveNext(); // move on 2nd entry + File.Move(nextEnumerator.Current, enumerator.Current); enumerator.MoveNext(); - while (nextEnumerator.MoveNext()) - { - File.Move(nextEnumerator.Current, enumerator.Current); - enumerator.MoveNext(); - } - CreateFile(null, nextEnumerator.Current); + } + CreateFile(null, nextEnumerator.Current); - if (deleteLatestFile) - { - File.Delete(fileList.First.Value); - fileList.RemoveFirst(); - } - return fileList; + if (deleteLatestFile) + { + File.Delete(fileList.First.Value); + fileList.RemoveFirst(); } + return fileList; + } - protected void Cleanup() + protected void Cleanup() + { + try { - try - { - Directory.Delete(TEST_DIR_NAME, true); - } - catch (Exception) - { - } + Directory.Delete(TEST_DIR_NAME, true); } - - protected string CreateFile(DirectoryInfo dInfo, string fileName) + catch (Exception) { - int lineCount = 10; - string fullName = dInfo == null ? fileName : dInfo.FullName + Path.DirectorySeparatorChar + fileName; + } + } - using (StreamWriter writer = new(File.Create(fullName))) - { - for (int i = 1; i <= lineCount; ++i) - { - writer.WriteLine("Line number " + i.ToString("D3") + " of File " + fullName); - } + protected string CreateFile(DirectoryInfo dInfo, string fileName) + { + var lineCount = 10; + var fullName = dInfo == null ? fileName : dInfo.FullName + Path.DirectorySeparatorChar + fileName; - writer.Flush(); + using (StreamWriter writer = new(File.Create(fullName))) + { + for (var i = 1; i <= lineCount; ++i) + { + writer.WriteLine("Line number " + i.ToString("D3") + " of File " + fullName); } - return fullName; + writer.Flush(); } + + return fullName; } } \ No newline at end of file diff --git a/src/LogExpert.Tests/SquareBracketColumnizerTest.cs b/src/LogExpert.Tests/SquareBracketColumnizerTest.cs index e972f658..49f5db6c 100644 --- a/src/LogExpert.Tests/SquareBracketColumnizerTest.cs +++ b/src/LogExpert.Tests/SquareBracketColumnizerTest.cs @@ -8,40 +8,39 @@ using System.Collections.Generic; using System.IO; -namespace LogExpert.Tests +namespace LogExpert.Tests; + +[TestFixture] +public class SquareBracketColumnizerTest { - [TestFixture] - public class SquareBracketColumnizerTest + [TestCase(@".\TestData\SquareBracketColumnizerTest_01.txt", 5)] + [TestCase(@".\TestData\SquareBracketColumnizerTest_02.txt", 5)] + [TestCase(@".\TestData\SquareBracketColumnizerTest_03.txt", 6)] + [TestCase(@".\TestData\SquareBracketColumnizerTest_05.txt", 3)] + public void GetPriority_HappyFile_ColumnCountMatches(string fileName, int count) { - [TestCase(@".\TestData\SquareBracketColumnizerTest_01.txt", 5)] - [TestCase(@".\TestData\SquareBracketColumnizerTest_02.txt", 5)] - [TestCase(@".\TestData\SquareBracketColumnizerTest_03.txt", 6)] - [TestCase(@".\TestData\SquareBracketColumnizerTest_05.txt", 3)] - public void GetPriority_HappyFile_ColumnCountMatches(string fileName, int count) - { - SquareBracketColumnizer squareBracketColumnizer = new(); - string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName); - - LogfileReader logFileReader = new(path, new EncodingOptions(), true, 40, 50, new MultiFileOptions(), PluginRegistry.PluginRegistry.Instance); - logFileReader.ReadFiles(); - List loglines = new() - { - // Sampling a few lines to select the correct columnizer - logFileReader.GetLogLine(0), - logFileReader.GetLogLine(1), - logFileReader.GetLogLine(2), - logFileReader.GetLogLine(3), - logFileReader.GetLogLine(4), - logFileReader.GetLogLine(5), - logFileReader.GetLogLine(25), - logFileReader.GetLogLine(100), - logFileReader.GetLogLine(200), - logFileReader.GetLogLine(400) - }; + SquareBracketColumnizer squareBracketColumnizer = new(); + var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName); - squareBracketColumnizer.GetPriority(path, loglines); - Assert.That(count, Is.EqualTo(squareBracketColumnizer.GetColumnCount())); - } + LogfileReader logFileReader = new(path, new EncodingOptions(), true, 40, 50, new MultiFileOptions(), PluginRegistry.PluginRegistry.Instance); + logFileReader.ReadFiles(); + List loglines = new() + { + // Sampling a few lines to select the correct columnizer + logFileReader.GetLogLine(0), + logFileReader.GetLogLine(1), + logFileReader.GetLogLine(2), + logFileReader.GetLogLine(3), + logFileReader.GetLogLine(4), + logFileReader.GetLogLine(5), + logFileReader.GetLogLine(25), + logFileReader.GetLogLine(100), + logFileReader.GetLogLine(200), + logFileReader.GetLogLine(400) + }; + squareBracketColumnizer.GetPriority(path, loglines); + Assert.That(count, Is.EqualTo(squareBracketColumnizer.GetColumnCount())); } + } \ No newline at end of file diff --git a/src/LogExpert.UI/Controls/BufferedDataGridView.cs b/src/LogExpert.UI/Controls/BufferedDataGridView.cs index afb248a2..e279178f 100644 --- a/src/LogExpert.UI/Controls/BufferedDataGridView.cs +++ b/src/LogExpert.UI/Controls/BufferedDataGridView.cs @@ -1,13 +1,10 @@ -using LogExpert.Core.Entities; +using System.Drawing.Drawing2D; + +using LogExpert.Core.Entities; using LogExpert.Core.EventArguments; using LogExpert.UI.Controls; -using NLog; -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Windows.Forms; +using NLog; namespace LogExpert.Dialogs; @@ -35,7 +32,7 @@ public partial class BufferedDataGridView : DataGridView #region cTor - public BufferedDataGridView() + public BufferedDataGridView () { _pen = new Pen(_bubbleColor, (float)3.0); _brush = new SolidBrush(_bubbleColor); @@ -49,7 +46,7 @@ public BufferedDataGridView() #region Delegates - public delegate void OverlayDoubleClickedEventHandler(object sender, OverlayEventArgs e); + public delegate void OverlayDoubleClickedEventHandler (object sender, OverlayEventArgs e); #endregion @@ -68,15 +65,15 @@ public Graphics Buffer } */ - public ContextMenuStrip EditModeMenuStrip { get; set; } = null; + public ContextMenuStrip EditModeMenuStrip { get; set; } - public bool PaintWithOverlays { get; set; } = false; + public bool PaintWithOverlays { get; set; } #endregion #region Public methods - public void AddOverlay(BookmarkOverlay overlay) + public void AddOverlay (BookmarkOverlay overlay) { lock (_overlayList) { @@ -88,7 +85,7 @@ public void AddOverlay(BookmarkOverlay overlay) #region Overrides - protected override void OnPaint(PaintEventArgs e) + protected override void OnPaint (PaintEventArgs e) { try { @@ -107,19 +104,19 @@ protected override void OnPaint(PaintEventArgs e) } } - protected override void OnEditingControlShowing(DataGridViewEditingControlShowingEventArgs e) + protected override void OnEditingControlShowing (DataGridViewEditingControlShowingEventArgs e) { base.OnEditingControlShowing(e); e.Control.KeyDown -= OnControlKeyDown; e.Control.KeyDown += OnControlKeyDown; - DataGridViewTextBoxEditingControl editControl = (DataGridViewTextBoxEditingControl)e.Control; + var editControl = (DataGridViewTextBoxEditingControl)e.Control; e.Control.PreviewKeyDown -= Control_PreviewKeyDown; e.Control.PreviewKeyDown += Control_PreviewKeyDown; editControl.ContextMenuStrip = EditModeMenuStrip; } - protected override void OnMouseDown(MouseEventArgs e) + protected override void OnMouseDown (MouseEventArgs e) { BookmarkOverlay overlay = GetOverlayForPosition(e.Location); if (overlay != null) @@ -148,7 +145,7 @@ protected override void OnMouseDown(MouseEventArgs e) } } - protected override void OnMouseUp(MouseEventArgs e) + protected override void OnMouseUp (MouseEventArgs e) { if (_isDrag) { @@ -161,7 +158,7 @@ protected override void OnMouseUp(MouseEventArgs e) } } - protected override void OnMouseMove(MouseEventArgs e) + protected override void OnMouseMove (MouseEventArgs e) { if (_isDrag) { @@ -178,7 +175,7 @@ protected override void OnMouseMove(MouseEventArgs e) } } - protected override void OnMouseDoubleClick(MouseEventArgs e) + protected override void OnMouseDoubleClick (MouseEventArgs e) { BookmarkOverlay overlay = GetOverlayForPosition(e.Location); if (overlay != null) @@ -198,7 +195,7 @@ protected override void OnMouseDoubleClick(MouseEventArgs e) #region Private Methods - private BookmarkOverlay GetOverlayForPosition(Point pos) + private BookmarkOverlay GetOverlayForPosition (Point pos) { lock (_overlayList) { @@ -214,7 +211,7 @@ private BookmarkOverlay GetOverlayForPosition(Point pos) return null; } - private void PaintOverlays(PaintEventArgs e) + private void PaintOverlays (PaintEventArgs e) { BufferedGraphicsContext currentContext = BufferedGraphicsManager.Current; @@ -277,7 +274,7 @@ private void PaintOverlays(PaintEventArgs e) #region Events handler - private void Control_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) + private void Control_PreviewKeyDown (object sender, PreviewKeyDownEventArgs e) { if ((e.KeyCode == Keys.C || e.KeyCode == Keys.Insert) && e.Control) { @@ -288,7 +285,7 @@ private void Control_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) } } - private void OnControlKeyDown(object sender, KeyEventArgs e) + private void OnControlKeyDown (object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down) { @@ -297,7 +294,7 @@ private void OnControlKeyDown(object sender, KeyEventArgs e) if (EditingControl is LogCellEditingControl editControl) { editControl.EditingControlDataGridView.EndEdit(); - int line = editControl.EditingControlDataGridView.CurrentCellAddress.Y; + var line = editControl.EditingControlDataGridView.CurrentCellAddress.Y; if (e.KeyCode == Keys.Up) { if (line > 0) @@ -314,9 +311,9 @@ private void OnControlKeyDown(object sender, KeyEventArgs e) } } - int col = editControl.EditingControlDataGridView.CurrentCellAddress.X; - int scrollIndex = editControl.EditingControlDataGridView.HorizontalScrollingOffset; - int selStart = editControl.SelectionStart; + var col = editControl.EditingControlDataGridView.CurrentCellAddress.X; + var scrollIndex = editControl.EditingControlDataGridView.HorizontalScrollingOffset; + var selStart = editControl.SelectionStart; editControl.EditingControlDataGridView.CurrentCell = editControl.EditingControlDataGridView.Rows[line].Cells[col]; editControl.EditingControlDataGridView.BeginEdit(false); editControl.SelectionStart = selStart; @@ -332,10 +329,10 @@ private void OnControlKeyDown(object sender, KeyEventArgs e) } } - #endregion - - protected virtual void OnOverlayDoubleClicked(OverlayEventArgs e) + protected virtual void OnOverlayDoubleClicked (OverlayEventArgs e) { OverlayDoubleClicked?.Invoke(this, e); } + + #endregion } diff --git a/src/LogExpert.UI/Controls/ColorComboBox.cs b/src/LogExpert.UI/Controls/ColorComboBox.cs index 352eead1..2cc8dcd1 100644 --- a/src/LogExpert.UI/Controls/ColorComboBox.cs +++ b/src/LogExpert.UI/Controls/ColorComboBox.cs @@ -69,7 +69,7 @@ private void OnColorComboBoxDrawItem(object sender, DrawItemEventArgs e) if (e.Index >= 0) { Rectangle rectangle = new(4, e.Bounds.Top + 2, 30, e.Bounds.Height - 4); - Color rectColor = (Color)Items[e.Index]; + var rectColor = (Color)Items[e.Index]; e.Graphics.FillRectangle(new SolidBrush(rectColor), rectangle); e.Graphics.DrawRectangle(Pens.Black, rectangle); diff --git a/src/LogExpert.UI/Controls/DateTimeDragControl.cs b/src/LogExpert.UI/Controls/DateTimeDragControl.cs index ad17a7fd..8ae0e23f 100644 --- a/src/LogExpert.UI/Controls/DateTimeDragControl.cs +++ b/src/LogExpert.UI/Controls/DateTimeDragControl.cs @@ -10,503 +10,502 @@ using System.Linq; using System.Windows.Forms; -namespace LogExpert.Dialogs +namespace LogExpert.Dialogs; + +/// +/// This control displays date and time and allows user to interact with the individual parts using the mouse +/// to increment and decrement the values. The date format displayed is derived from the application UI locale. +/// We currently support only three: US (mm/dd/yyyy), French (yyyy-mm-dd) and German (dd.mm.yyyy). +/// The control raises events (ValueChanged, ValueDragged) when the date/time changes so that owner can react accordingly. +/// +public partial class DateTimeDragControl : UserControl { - /// - /// This control displays date and time and allows user to interact with the individual parts using the mouse - /// to increment and decrement the values. The date format displayed is derived from the application UI locale. - /// We currently support only three: US (mm/dd/yyyy), French (yyyy-mm-dd) and German (dd.mm.yyyy). - /// The control raises events (ValueChanged, ValueDragged) when the date/time changes so that owner can react accordingly. - /// - public partial class DateTimeDragControl : UserControl - { - #region Fields + #region Fields - private const int NO_DIGIT_DRAGGED = -1; - private int _addedValue; + private const int NO_DIGIT_DRAGGED = -1; + private int _addedValue; - private DateTime _dateTime; - private readonly IList _digitRects = new List(); - private readonly StringFormat _digitsFormat = new(); - private int _draggedDigit; + private DateTime _dateTime; + private readonly IList _digitRects = new List(); + private readonly StringFormat _digitsFormat = new(); + private int _draggedDigit; - public DragOrientationsEnum dragOrientation = DragOrientationsEnum.Vertical; + public DragOrientationsEnum dragOrientation = DragOrientationsEnum.Vertical; - private readonly ToolStripItem toolStripItemHorizontalDrag = new ToolStripMenuItem(); - private readonly ToolStripItem toolStripItemVerticalDrag = new ToolStripMenuItem(); - private readonly ToolStripItem toolStripItemVerticalInvertedDrag = new ToolStripMenuItem(); + private readonly ToolStripItem toolStripItemHorizontalDrag = new ToolStripMenuItem(); + private readonly ToolStripItem toolStripItemVerticalDrag = new ToolStripMenuItem(); + private readonly ToolStripItem toolStripItemVerticalInvertedDrag = new ToolStripMenuItem(); - private int _oldValue; + private int _oldValue; - private string[] _dateParts; + private string[] _dateParts; - private int _startMouseX; - private int _startMouseY; + private int _startMouseX; + private int _startMouseY; - #endregion + #endregion - #region cTor + #region cTor - /// - /// Default Constructor - /// - public DateTimeDragControl() - { - InitializeComponent(); + /// + /// Default Constructor + /// + public DateTimeDragControl() + { + InitializeComponent(); - AutoScaleDimensions = new SizeF(96F, 96F); - AutoScaleMode = AutoScaleMode.Dpi; + AutoScaleDimensions = new SizeF(96F, 96F); + AutoScaleMode = AutoScaleMode.Dpi; - _digitsFormat.LineAlignment = StringAlignment.Center; - _digitsFormat.Alignment = StringAlignment.Near; - _digitsFormat.Trimming = StringTrimming.None; - _digitsFormat.FormatFlags = StringFormatFlags.FitBlackBox | StringFormatFlags.NoClip | StringFormatFlags.NoWrap; + _digitsFormat.LineAlignment = StringAlignment.Center; + _digitsFormat.Alignment = StringAlignment.Near; + _digitsFormat.Trimming = StringTrimming.None; + _digitsFormat.FormatFlags = StringFormatFlags.FitBlackBox | StringFormatFlags.NoClip | StringFormatFlags.NoWrap; - _draggedDigit = NO_DIGIT_DRAGGED; - } + _draggedDigit = NO_DIGIT_DRAGGED; + } - #endregion + #endregion - #region Delegates + #region Delegates - public delegate void ValueChangedEventHandler(object sender, EventArgs e); + public delegate void ValueChangedEventHandler(object sender, EventArgs e); - public delegate void ValueDraggedEventHandler(object sender, EventArgs e); + public delegate void ValueDraggedEventHandler(object sender, EventArgs e); - #endregion + #endregion - #region Events + #region Events - public event ValueChangedEventHandler ValueChanged; - public event ValueDraggedEventHandler ValueDragged; + public event ValueChangedEventHandler ValueChanged; + public event ValueDraggedEventHandler ValueDragged; - #endregion + #endregion - #region Properties + #region Properties - public DateTime MinDateTime { get; set; } = DateTime.MinValue; + public DateTime MinDateTime { get; set; } = DateTime.MinValue; - public DateTime MaxDateTime { get; set; } = DateTime.MaxValue; + public DateTime MaxDateTime { get; set; } = DateTime.MaxValue; - public DragOrientationsEnum DragOrientation + public DragOrientationsEnum DragOrientation + { + get => dragOrientation; + set { - get => dragOrientation; - set - { - dragOrientation = value; - UpdateContextMenu(); - } + dragOrientation = value; + UpdateContextMenu(); } + } - public Color HoverColor { get; set; } + public Color HoverColor { get; set; } - public DateTime DateTime + public DateTime DateTime + { + get => _dateTime.Subtract(TimeSpan.FromMilliseconds(_dateTime.Millisecond)); + set { - get => _dateTime.Subtract(TimeSpan.FromMilliseconds(_dateTime.Millisecond)); - set - { - _dateTime = value; + _dateTime = value; - if (_dateTime < MinDateTime) - { - _dateTime = MinDateTime; - } - if (_dateTime > MaxDateTime) - { - _dateTime = MaxDateTime; - } + if (_dateTime < MinDateTime) + { + _dateTime = MinDateTime; + } + if (_dateTime > MaxDateTime) + { + _dateTime = MaxDateTime; } } + } - #endregion + #endregion - #region Private Methods + #region Private Methods - // Returns the index of the rectangle (digitRects) under the mouse cursor - private int DetermineDraggedDigit(MouseEventArgs e) + // Returns the index of the rectangle (digitRects) under the mouse cursor + private int DetermineDraggedDigit(MouseEventArgs e) + { + for (var i = 0; i < _digitRects.Count; ++i) { - for (int i = 0; i < _digitRects.Count; ++i) + if (_digitRects[i].Contains(e.Location) && Token.IsDatePart(_dateParts[i])) { - if (_digitRects[i].Contains(e.Location) && Token.IsDatePart(_dateParts[i])) - { - return i; - } + return i; } - - return NO_DIGIT_DRAGGED; } - // Return the value corresponding to current dragged digit - private int GetDraggedValue() + return NO_DIGIT_DRAGGED; + } + + // Return the value corresponding to current dragged digit + private int GetDraggedValue() + { + var datePart = _dateParts[_draggedDigit]; + + if (datePart.StartsWith("y", StringComparison.OrdinalIgnoreCase)) { - string datePart = _dateParts[_draggedDigit]; + return _dateTime.Year; + } - if (datePart.StartsWith("y", StringComparison.OrdinalIgnoreCase)) - { - return _dateTime.Year; - } + if (datePart.StartsWith("M")) + { + return _dateTime.Month; + } - if (datePart.StartsWith("M")) - { - return _dateTime.Month; - } + if (datePart.StartsWith("d", StringComparison.OrdinalIgnoreCase)) + { + return _dateTime.Day; + } - if (datePart.StartsWith("d", StringComparison.OrdinalIgnoreCase)) - { - return _dateTime.Day; - } + if (datePart.StartsWith("h", StringComparison.OrdinalIgnoreCase)) + { + return _dateTime.Hour; + } - if (datePart.StartsWith("h", StringComparison.OrdinalIgnoreCase)) - { - return _dateTime.Hour; - } + if (datePart.StartsWith("m")) + { + return _dateTime.Minute; + } - if (datePart.StartsWith("m")) - { - return _dateTime.Minute; - } + return datePart.StartsWith("s", StringComparison.OrdinalIgnoreCase) ? _dateTime.Second : NO_DIGIT_DRAGGED; + } - return datePart.StartsWith("s", StringComparison.OrdinalIgnoreCase) ? _dateTime.Second : NO_DIGIT_DRAGGED; + private bool SetDraggedValue(int delta) + { + if (_draggedDigit == NO_DIGIT_DRAGGED) + { + return false; } - private bool SetDraggedValue(int delta) + var changed = true; + try { - if (_draggedDigit == NO_DIGIT_DRAGGED) + var datePart = _dateParts[_draggedDigit]; + + if (datePart.StartsWith("y", StringComparison.OrdinalIgnoreCase)) { - return false; + _dateTime = _dateTime.AddYears(delta); } - - bool changed = true; - try + else if (datePart.StartsWith("M")) { - string datePart = _dateParts[_draggedDigit]; - - if (datePart.StartsWith("y", StringComparison.OrdinalIgnoreCase)) - { - _dateTime = _dateTime.AddYears(delta); - } - else if (datePart.StartsWith("M")) - { - _dateTime = _dateTime.AddMonths(delta); - } - else if (datePart.StartsWith("d", StringComparison.OrdinalIgnoreCase)) - { - _dateTime = _dateTime.AddDays(delta); - } - else if (datePart.StartsWith("h", StringComparison.OrdinalIgnoreCase)) - { - _dateTime = _dateTime.AddHours(delta); - } - else if (datePart.StartsWith("m")) - { - _dateTime = _dateTime.AddMinutes(delta); - } - else if (datePart.StartsWith("s", StringComparison.OrdinalIgnoreCase)) - { - _dateTime = _dateTime.AddSeconds(delta); - } + _dateTime = _dateTime.AddMonths(delta); } - catch (Exception) + else if (datePart.StartsWith("d", StringComparison.OrdinalIgnoreCase)) { - // invalid value dragged + _dateTime = _dateTime.AddDays(delta); } - - if (_dateTime > MaxDateTime) + else if (datePart.StartsWith("h", StringComparison.OrdinalIgnoreCase)) { - _dateTime = MaxDateTime; - changed = false; + _dateTime = _dateTime.AddHours(delta); } - if (_dateTime < MinDateTime) + else if (datePart.StartsWith("m")) { - _dateTime = MinDateTime; - changed = false; + _dateTime = _dateTime.AddMinutes(delta); } - - return changed; + else if (datePart.StartsWith("s", StringComparison.OrdinalIgnoreCase)) + { + _dateTime = _dateTime.AddSeconds(delta); + } + } + catch (Exception) + { + // invalid value dragged } - private void InitCustomRects(Section dateSection) + if (_dateTime > MaxDateTime) { - _dateParts = dateSection - .GeneralTextDateDurationParts - .Select(DateFormatPartAdjuster.AdjustDateTimeFormatPart) - .ToArray(); + _dateTime = MaxDateTime; + changed = false; + } + if (_dateTime < MinDateTime) + { + _dateTime = MinDateTime; + changed = false; + } - Rectangle rect = ClientRectangle; - int oneCharWidth = rect.Width / _dateParts.Sum(s => s.Length); - int left = rect.Left; + return changed; + } - _digitRects.Clear(); + private void InitCustomRects(Section dateSection) + { + _dateParts = dateSection + .GeneralTextDateDurationParts + .Select(DateFormatPartAdjuster.AdjustDateTimeFormatPart) + .ToArray(); - foreach (string datePart in _dateParts) - { - int s = datePart.Length * oneCharWidth; - _digitRects.Add(new Rectangle(left, rect.Top, s, rect.Height)); - left += s; - } + Rectangle rect = ClientRectangle; + var oneCharWidth = rect.Width / _dateParts.Sum(s => s.Length); + var left = rect.Left; - } + _digitRects.Clear(); - private void InitDigitRects() + foreach (var datePart in _dateParts) { - CultureInfo culture = System.Threading.Thread.CurrentThread.CurrentCulture; + var s = datePart.Length * oneCharWidth; + _digitRects.Add(new Rectangle(left, rect.Top, s, rect.Height)); + left += s; + } - string datePattern = string.Concat(culture.DateTimeFormat.ShortDatePattern, " ", culture.DateTimeFormat.LongTimePattern); + } - List
sections = Parser.ParseSections(datePattern, out _); - Section dateSection = sections.FirstOrDefault(); + private void InitDigitRects() + { + CultureInfo culture = System.Threading.Thread.CurrentThread.CurrentCulture; - if (dateSection == null) - { - sections = Parser.ParseSections("dd.MM.yyyy HH:mm:ss", out bool _); - dateSection = sections.Single(); - } + var datePattern = string.Concat(culture.DateTimeFormat.ShortDatePattern, " ", culture.DateTimeFormat.LongTimePattern); + + List
sections = Parser.ParseSections(datePattern, out _); + Section dateSection = sections.FirstOrDefault(); - InitCustomRects(dateSection); + if (dateSection == null) + { + sections = Parser.ParseSections("dd.MM.yyyy HH:mm:ss", out var _); + dateSection = sections.Single(); } - #endregion + InitCustomRects(dateSection); + } - #region Events handler + #endregion - private void DateTimeDragControl_Load(object sender, EventArgs e) - { - InitDigitRects(); + #region Events handler - BuildContextualMenu(); - } + private void DateTimeDragControl_Load(object sender, EventArgs e) + { + InitDigitRects(); - #endregion + BuildContextualMenu(); + } - protected void OnValueChanged(EventArgs e) - { - ValueChanged?.Invoke(this, e); - } + #endregion - protected void OnValueDragged(EventArgs e) - { - ValueDragged?.Invoke(this, e); - } + protected void OnValueChanged(EventArgs e) + { + ValueChanged?.Invoke(this, e); + } - #region Contextual Menu + protected void OnValueDragged(EventArgs e) + { + ValueDragged?.Invoke(this, e); + } - private void BuildContextualMenu() - { - ContextMenuStrip = new ContextMenuStrip(); - ContextMenuStrip.Name = "Timestamp selector"; - ContextMenuStrip.Items.Add(toolStripItemHorizontalDrag); - ContextMenuStrip.Items.Add(toolStripItemVerticalDrag); - ContextMenuStrip.Items.Add(toolStripItemVerticalInvertedDrag); + #region Contextual Menu - toolStripItemHorizontalDrag.Click += OnToolStripItemHorizontalDragClick; - toolStripItemHorizontalDrag.Text = "Drag horizontal"; + private void BuildContextualMenu() + { + ContextMenuStrip = new ContextMenuStrip(); + ContextMenuStrip.Name = "Timestamp selector"; + ContextMenuStrip.Items.Add(toolStripItemHorizontalDrag); + ContextMenuStrip.Items.Add(toolStripItemVerticalDrag); + ContextMenuStrip.Items.Add(toolStripItemVerticalInvertedDrag); - toolStripItemVerticalDrag.Click += OnToolStripItemVerticalDragClick; - toolStripItemVerticalDrag.Text = "Drag vertical"; + toolStripItemHorizontalDrag.Click += OnToolStripItemHorizontalDragClick; + toolStripItemHorizontalDrag.Text = "Drag horizontal"; - toolStripItemVerticalInvertedDrag.Click += OnToolStripItemVerticalInvertedDragClick; - toolStripItemVerticalInvertedDrag.Text = "Drag vertical inverted"; + toolStripItemVerticalDrag.Click += OnToolStripItemVerticalDragClick; + toolStripItemVerticalDrag.Text = "Drag vertical"; - ContextMenuStrip.Opening += OnContextMenuStripOpening; + toolStripItemVerticalInvertedDrag.Click += OnToolStripItemVerticalInvertedDragClick; + toolStripItemVerticalInvertedDrag.Text = "Drag vertical inverted"; - UpdateContextMenu(); - } + ContextMenuStrip.Opening += OnContextMenuStripOpening; - private void UpdateContextMenu() - { - toolStripItemHorizontalDrag.Enabled = DragOrientation != DragOrientationsEnum.Horizontal; - toolStripItemVerticalDrag.Enabled = DragOrientation != DragOrientationsEnum.Vertical; - toolStripItemVerticalInvertedDrag.Enabled = DragOrientation != DragOrientationsEnum.InvertedVertical; - } + UpdateContextMenu(); + } - private void OnContextMenuStripOpening(object sender, CancelEventArgs e) - { - if (Capture) - { - e.Cancel = true; - } - } + private void UpdateContextMenu() + { + toolStripItemHorizontalDrag.Enabled = DragOrientation != DragOrientationsEnum.Horizontal; + toolStripItemVerticalDrag.Enabled = DragOrientation != DragOrientationsEnum.Vertical; + toolStripItemVerticalInvertedDrag.Enabled = DragOrientation != DragOrientationsEnum.InvertedVertical; + } - private void OnToolStripItemHorizontalDragClick(object sender, EventArgs e) + private void OnContextMenuStripOpening(object sender, CancelEventArgs e) + { + if (Capture) { - DragOrientation = DragOrientationsEnum.Horizontal; - toolStripItemHorizontalDrag.Enabled = false; - toolStripItemVerticalDrag.Enabled = true; - toolStripItemVerticalInvertedDrag.Enabled = true; + e.Cancel = true; } + } - private void OnToolStripItemVerticalDragClick(object sender, EventArgs e) - { - DragOrientation = DragOrientationsEnum.Vertical; - toolStripItemHorizontalDrag.Enabled = true; - toolStripItemVerticalDrag.Enabled = false; - toolStripItemVerticalInvertedDrag.Enabled = true; - } + private void OnToolStripItemHorizontalDragClick(object sender, EventArgs e) + { + DragOrientation = DragOrientationsEnum.Horizontal; + toolStripItemHorizontalDrag.Enabled = false; + toolStripItemVerticalDrag.Enabled = true; + toolStripItemVerticalInvertedDrag.Enabled = true; + } - private void OnToolStripItemVerticalInvertedDragClick(object sender, EventArgs e) - { - DragOrientation = DragOrientationsEnum.InvertedVertical; - toolStripItemHorizontalDrag.Enabled = true; - toolStripItemVerticalDrag.Enabled = true; - toolStripItemVerticalInvertedDrag.Enabled = false; - } + private void OnToolStripItemVerticalDragClick(object sender, EventArgs e) + { + DragOrientation = DragOrientationsEnum.Vertical; + toolStripItemHorizontalDrag.Enabled = true; + toolStripItemVerticalDrag.Enabled = false; + toolStripItemVerticalInvertedDrag.Enabled = true; + } - #endregion + private void OnToolStripItemVerticalInvertedDragClick(object sender, EventArgs e) + { + DragOrientation = DragOrientationsEnum.InvertedVertical; + toolStripItemHorizontalDrag.Enabled = true; + toolStripItemVerticalDrag.Enabled = true; + toolStripItemVerticalInvertedDrag.Enabled = false; + } - #region Rendering + #endregion - protected override void OnPaint(PaintEventArgs e) - { - base.OnPaint(e); + #region Rendering - // Show what digit is dragged - using (Brush hoverBrush = new SolidBrush(HoverColor)) + protected override void OnPaint(PaintEventArgs e) + { + base.OnPaint(e); + + // Show what digit is dragged + using (Brush hoverBrush = new SolidBrush(HoverColor)) + { + if (_draggedDigit != NO_DIGIT_DRAGGED) { - if (_draggedDigit != NO_DIGIT_DRAGGED) - { - e.Graphics.FillRectangle(hoverBrush, _digitRects[_draggedDigit]); - } + e.Graphics.FillRectangle(hoverBrush, _digitRects[_draggedDigit]); } + } - // Display current value with user-defined date format and fixed time format ("HH:mm:ss") - using (Brush brush = new SolidBrush(Color.Black)) + // Display current value with user-defined date format and fixed time format ("HH:mm:ss") + using (Brush brush = new SolidBrush(Color.Black)) + { + for (var i = 0; i < _dateParts.Length; i++) { - for (int i = 0; i < _dateParts.Length; i++) - { - string datePart = _dateParts[i]; - Rectangle rect = _digitRects[i]; - string value; + var datePart = _dateParts[i]; + Rectangle rect = _digitRects[i]; + string value; - if (Token.IsDatePart(datePart)) + if (Token.IsDatePart(datePart)) + { + try { - try - { - value = _dateTime.ToString("-" + datePart + "-"); - value = value.Substring(1, value.Length - 2); - } - catch - { - value = datePart; - } + value = _dateTime.ToString("-" + datePart + "-"); + value = value.Substring(1, value.Length - 2); } - else + catch { value = datePart; } - - e.Graphics.DrawString(value, Font, brush, rect, _digitsFormat); } - } - } + else + { + value = datePart; + } - private void DateTimeDragControl_Resize(object sender, EventArgs e) - { - InitDigitRects(); + e.Graphics.DrawString(value, Font, brush, rect, _digitsFormat); + } } + } - #endregion + private void DateTimeDragControl_Resize(object sender, EventArgs e) + { + InitDigitRects(); + } - #region Mouse callbacks + #endregion - protected override void OnMouseDown(MouseEventArgs e) - { - base.OnMouseDown(e); + #region Mouse callbacks - if (e.Button == MouseButtons.Left) - { - _draggedDigit = DetermineDraggedDigit(e); - if (_draggedDigit == NO_DIGIT_DRAGGED) - { - return; - } - Capture = true; - _startMouseY = e.Y; - _startMouseX = e.X; - _oldValue = GetDraggedValue(); - _addedValue = 0; - } - else if (e.Button == MouseButtons.Right && Capture) - { - Capture = false; - SetDraggedValue(0); //undo - } - Invalidate(); // repaint with the selected item (or none) - } + protected override void OnMouseDown(MouseEventArgs e) + { + base.OnMouseDown(e); - protected override void OnMouseUp(MouseEventArgs e) + if (e.Button == MouseButtons.Left) { - if (!Capture) + _draggedDigit = DetermineDraggedDigit(e); + if (_draggedDigit == NO_DIGIT_DRAGGED) { return; } - - base.OnMouseUp(e); - + Capture = true; + _startMouseY = e.Y; + _startMouseX = e.X; + _oldValue = GetDraggedValue(); + _addedValue = 0; + } + else if (e.Button == MouseButtons.Right && Capture) + { Capture = false; - _draggedDigit = NO_DIGIT_DRAGGED; - Invalidate(); // repaint without the selected item - - OnValueChanged(EventArgs.Empty); + SetDraggedValue(0); //undo } + Invalidate(); // repaint with the selected item (or none) + } - protected override void OnMouseMove(MouseEventArgs e) + protected override void OnMouseUp(MouseEventArgs e) + { + if (!Capture) { - base.OnMouseMove(e); + return; + } - if (!Capture) - { - return; - } + base.OnMouseUp(e); - int diff; - switch (DragOrientation) - { - case DragOrientationsEnum.Vertical: - { - diff = _startMouseY - e.Y; - break; - } - case DragOrientationsEnum.InvertedVertical: - { - diff = _startMouseY + e.Y; - break; - } - default: - { - diff = e.X - _startMouseX; - break; - } - } + Capture = false; + _draggedDigit = NO_DIGIT_DRAGGED; + Invalidate(); // repaint without the selected item - int delta = diff / 5 - _addedValue; // one unit per 5 pixels move + OnValueChanged(EventArgs.Empty); + } - if (delta == 0) - { - return; - } + protected override void OnMouseMove(MouseEventArgs e) + { + base.OnMouseMove(e); - if (SetDraggedValue(delta)) - { - _addedValue += delta; - } + if (!Capture) + { + return; + } - Invalidate(); + int diff; + switch (DragOrientation) + { + case DragOrientationsEnum.Vertical: + { + diff = _startMouseY - e.Y; + break; + } + case DragOrientationsEnum.InvertedVertical: + { + diff = _startMouseY + e.Y; + break; + } + default: + { + diff = e.X - _startMouseX; + break; + } + } + + var delta = diff / 5 - _addedValue; // one unit per 5 pixels move - OnValueDragged(EventArgs.Empty); + if (delta == 0) + { + return; } - private void DateTimeDragControl_MouseLeave(object sender, EventArgs e) + if (SetDraggedValue(delta)) { - if (Capture) - { - return; - } + _addedValue += delta; + } - _draggedDigit = NO_DIGIT_DRAGGED; - Refresh(); + Invalidate(); + + OnValueDragged(EventArgs.Empty); + } + + private void DateTimeDragControl_MouseLeave(object sender, EventArgs e) + { + if (Capture) + { + return; } - #endregion + _draggedDigit = NO_DIGIT_DRAGGED; + Refresh(); } + + #endregion } diff --git a/src/LogExpert.UI/Controls/KnobControl.cs b/src/LogExpert.UI/Controls/KnobControl.cs index fc2c1c0e..b63eb5c4 100644 --- a/src/LogExpert.UI/Controls/KnobControl.cs +++ b/src/LogExpert.UI/Controls/KnobControl.cs @@ -14,10 +14,10 @@ public partial class KnobControl : UserControl private readonly StringFormat _stringFormat = new(); - private bool _isShiftPressed = false; + private bool _isShiftPressed; - private int _oldValue = 0; - private int _startMouseY = 0; + private int _oldValue; + private int _startMouseY; private int _value; #endregion @@ -53,7 +53,7 @@ public KnobControl() public int Value { - get { return _value; } + get => _value; set { _value = value; @@ -62,10 +62,7 @@ public int Value } - public int Range - { - get { return MaxValue - MinValue; } - } + public int Range => MaxValue - MinValue; public int DragSensitivity { get; set; } = 3; @@ -83,7 +80,7 @@ protected override void OnPaint(PaintEventArgs e) Pen greyPen = new(Color.Gray, 1); Rectangle rect = ClientRectangle; - int height = Font.Height + 3; + var height = Font.Height + 3; if (height > rect.Height) { height = rect.Height + 3; @@ -95,8 +92,8 @@ protected override void OnPaint(PaintEventArgs e) //rect = this.ClientRectangle; rect.Inflate(-2, -2); - float startAngle = 135.0F + 270F * ((float)_value / (float)Range); - float sweepAngle = 0.1F; + var startAngle = 135.0F + 270F * ((float)_value / (float)Range); + var sweepAngle = 0.1F; e.Graphics.DrawPie(blackPen, rect, startAngle, sweepAngle); Brush brush = new SolidBrush(foregroundColor); @@ -147,11 +144,11 @@ protected override void OnMouseMove(MouseEventArgs e) return; } - int sense = _isShiftPressed ? DragSensitivity * 2 : DragSensitivity; + var sense = _isShiftPressed ? DragSensitivity * 2 : DragSensitivity; - int diff = _startMouseY - e.Y; + var diff = _startMouseY - e.Y; _logger.Debug("KnobDiff: {0}", diff); - int range = MaxValue - MinValue; + var range = MaxValue - MinValue; _value = _oldValue + diff / sense; if (_value < MinValue) diff --git a/src/LogExpert.UI/Controls/LogGridCell.cs b/src/LogExpert.UI/Controls/LogGridCell.cs index 70ca04bd..fe870e1b 100644 --- a/src/LogExpert.UI/Controls/LogGridCell.cs +++ b/src/LogExpert.UI/Controls/LogGridCell.cs @@ -1,14 +1,13 @@ using System; using System.Windows.Forms; -namespace LogExpert.UI.Controls +namespace LogExpert.UI.Controls; + +public class LogGridCell : DataGridViewTextBoxCell { - public class LogGridCell : DataGridViewTextBoxCell - { - #region Properties + #region Properties - public override Type EditType => typeof(LogCellEditingControl); + public override Type EditType => typeof(LogCellEditingControl); - #endregion - } + #endregion } diff --git a/src/LogExpert.UI/Controls/LogTextColumn.cs b/src/LogExpert.UI/Controls/LogTextColumn.cs index a4f5e291..2bca5e54 100644 --- a/src/LogExpert.UI/Controls/LogTextColumn.cs +++ b/src/LogExpert.UI/Controls/LogTextColumn.cs @@ -1,15 +1,14 @@ using System.Windows.Forms; -namespace LogExpert.UI.Controls -{ - public class LogTextColumn : DataGridViewColumn - { - #region cTor +namespace LogExpert.UI.Controls; - public LogTextColumn() : base(new LogGridCell()) - { - } +public class LogTextColumn : DataGridViewColumn +{ + #region cTor - #endregion + public LogTextColumn() : base(new LogGridCell()) + { } + + #endregion } diff --git a/src/LogExpert.UI/Controls/LogWindow/LogWindow.cs b/src/LogExpert.UI/Controls/LogWindow/LogWindow.cs index 9cd0514e..dec9982f 100644 --- a/src/LogExpert.UI/Controls/LogWindow/LogWindow.cs +++ b/src/LogExpert.UI/Controls/LogWindow/LogWindow.cs @@ -93,7 +93,7 @@ public partial class LogWindow : DockContent, ILogPaintContextUI, ILogView, ILog private string[] _fileNames; private List _filterHitList = []; private FilterParams _filterParams = new(); - private int _filterPipeNameCounter = 0; + private int _filterPipeNameCounter; private List _filterResultList = []; private EventWaitHandle _filterUpdateEvent = new ManualResetEvent(false); @@ -109,7 +109,7 @@ public partial class LogWindow : DockContent, ILogPaintContextUI, ILogView, ILog private bool _isTimestampDisplaySyncing; private List _lastFilterLinesList = []; - private int _lineHeight = 0; + private int _lineHeight; internal LogfileReader _logFileReader; private MultiFileOptions _multiFileOptions = new(); @@ -118,15 +118,15 @@ public partial class LogWindow : DockContent, ILogPaintContextUI, ILogView, ILog private PatternWindow _patternWindow; private ReloadMemento _reloadMemento; - private int _reloadOverloadCounter = 0; + private int _reloadOverloadCounter; private SortedList _rowHeightList = []; - private int _selectedCol = 0; // set by context menu event for column headers only + private int _selectedCol; // set by context menu event for column headers only private bool _shouldCallTimeSync; private bool _shouldCancel; private bool _shouldTimestampDisplaySyncingCancel; private bool _showAdvanced; private List _tempHighlightEntryList = []; - private int _timeShiftSyncLine = 0; + private int _timeShiftSyncLine; private bool _waitingForClose; @@ -190,7 +190,7 @@ public LogWindow (LogTabWindow.LogTabWindow parent, string fileName, bool isTemp //this.toolwinTabControl.TabPages.Add(this.bookmarkWindow); _filterParams = new FilterParams(); - foreach (string item in configManager.Settings.filterHistoryList) + foreach (var item in configManager.Settings.filterHistoryList) { filterComboBox.Items.Add(item); } @@ -460,7 +460,7 @@ public bool ShowBookmarkBubbles public string FileName { get; private set; } - public string SessionFileName { get; set; } = null; + public string SessionFileName { get; set; } public bool IsMultiFile { @@ -474,7 +474,7 @@ public bool IsMultiFile public string TempTitleName { get; set; } = ""; - internal FilterPipe FilterPipe { get; set; } = null; + internal FilterPipe FilterPipe { get; set; } public string Title { @@ -493,11 +493,11 @@ public string Title public bool ForcePersistenceLoading { get; set; } - public string ForcedPersistenceFileName { get; set; } = null; + public string ForcedPersistenceFileName { get; set; } public Preferences Preferences => ConfigManager.Settings.Preferences; - public string GivenFileName { get; set; } = null; + public string GivenFileName { get; set; } public TimeSyncList TimeSyncList { get; private set; } @@ -517,28 +517,14 @@ public string Title event FileSizeChangedEventHandler ILogWindow.FileSizeChanged { - add - { - this.FileSizeChanged += new FileSizeChangedEventHandler(value); - } - - remove - { - this.FileSizeChanged -= new FileSizeChangedEventHandler(value); - } + add => FileSizeChanged += new FileSizeChangedEventHandler(value); + remove => FileSizeChanged -= new FileSizeChangedEventHandler(value); } event EventHandler ILogWindow.TailFollowed { - add - { - this.TailFollowed += new TailFollowedEventHandler(value); - } - - remove - { - this.TailFollowed -= new TailFollowedEventHandler(value); - } + add => TailFollowed += new TailFollowedEventHandler(value); + remove => TailFollowed -= new TailFollowedEventHandler(value); } #endregion @@ -676,7 +662,7 @@ private void OnButtonSizeChanged (object sender, EventArgs e) #if DEBUG internal void DumpBufferInfo () { - int currentLineNum = dataGridView.CurrentCellAddress.Y; + var currentLineNum = dataGridView.CurrentCellAddress.Y; _logFileReader.LogBufferInfoForLine(currentLineNum); } diff --git a/src/LogExpert.UI/Controls/LogWindow/LogWindowEventHandlers.cs b/src/LogExpert.UI/Controls/LogWindow/LogWindowEventHandlers.cs index a61a0669..d18bf035 100644 --- a/src/LogExpert.UI/Controls/LogWindow/LogWindowEventHandlers.cs +++ b/src/LogExpert.UI/Controls/LogWindow/LogWindowEventHandlers.cs @@ -13,1623 +13,1622 @@ using LogExpert.UI.Entities; using LogExpert.UI.Extensions; -namespace LogExpert.UI.Controls.LogWindow +namespace LogExpert.UI.Controls.LogWindow; + +partial class LogWindow { - partial class LogWindow + private void AutoResizeFilterBox () { - private void AutoResizeFilterBox () - { - filterSplitContainer.SplitterDistance = filterComboBox.Left + filterComboBox.GetMaxTextWidth(); - } + filterSplitContainer.SplitterDistance = filterComboBox.Left + filterComboBox.GetMaxTextWidth(); + } - #region Events handler + #region Events handler - protected void OnProgressBarUpdate (ProgressEventArgs e) - { - ProgressBarUpdate?.Invoke(this, e); - } + protected void OnProgressBarUpdate (ProgressEventArgs e) + { + ProgressBarUpdate?.Invoke(this, e); + } - protected void OnStatusLine (StatusLineEventArgs e) - { - StatusLineEvent?.Invoke(this, e); - } + protected void OnStatusLine (StatusLineEventArgs e) + { + StatusLineEvent?.Invoke(this, e); + } - protected void OnGuiState (GuiStateArgs e) - { - GuiStateUpdate?.Invoke(this, e); - } + protected void OnGuiState (GuiStateArgs e) + { + GuiStateUpdate?.Invoke(this, e); + } - protected void OnTailFollowed (EventArgs e) - { - TailFollowed?.Invoke(this, e); - } + protected void OnTailFollowed (EventArgs e) + { + TailFollowed?.Invoke(this, e); + } - protected void OnFileNotFound (EventArgs e) - { - FileNotFound?.Invoke(this, e); - } + protected void OnFileNotFound (EventArgs e) + { + FileNotFound?.Invoke(this, e); + } - protected void OnFileRespawned (EventArgs e) - { - FileRespawned?.Invoke(this, e); - } + protected void OnFileRespawned (EventArgs e) + { + FileRespawned?.Invoke(this, e); + } - protected void OnFilterListChanged (LogWindow source) - { - FilterListChanged?.Invoke(this, new FilterListChangedEventArgs(source)); - } + protected void OnFilterListChanged (LogWindow source) + { + FilterListChanged?.Invoke(this, new FilterListChangedEventArgs(source)); + } - protected void OnCurrentHighlightListChanged () - { - CurrentHighlightGroupChanged?.Invoke(this, new CurrentHighlightGroupChangedEventArgs(this, _currentHighlightGroup)); - } + protected void OnCurrentHighlightListChanged () + { + CurrentHighlightGroupChanged?.Invoke(this, new CurrentHighlightGroupChangedEventArgs(this, _currentHighlightGroup)); + } - protected void OnBookmarkAdded () - { - BookmarkAdded?.Invoke(this, EventArgs.Empty); - } + protected void OnBookmarkAdded () + { + BookmarkAdded?.Invoke(this, EventArgs.Empty); + } - protected void OnBookmarkRemoved () - { - BookmarkRemoved?.Invoke(this, EventArgs.Empty); - } + protected void OnBookmarkRemoved () + { + BookmarkRemoved?.Invoke(this, EventArgs.Empty); + } - protected void OnBookmarkTextChanged (Bookmark bookmark) - { - BookmarkTextChanged?.Invoke(this, new BookmarkEventArgs(bookmark)); - } + protected void OnBookmarkTextChanged (Bookmark bookmark) + { + BookmarkTextChanged?.Invoke(this, new BookmarkEventArgs(bookmark)); + } - protected void OnColumnizerChanged (ILogLineColumnizer columnizer) - { - ColumnizerChanged?.Invoke(this, new ColumnizerEventArgs(columnizer)); - } + protected void OnColumnizerChanged (ILogLineColumnizer columnizer) + { + ColumnizerChanged?.Invoke(this, new ColumnizerEventArgs(columnizer)); + } - protected void OnRegisterCancelHandler (IBackgroundProcessCancelHandler handler) + protected void OnRegisterCancelHandler (IBackgroundProcessCancelHandler handler) + { + lock (_cancelHandlerList) { - lock (_cancelHandlerList) - { - _cancelHandlerList.Add(handler); - } + _cancelHandlerList.Add(handler); } + } - protected void OnDeRegisterCancelHandler (IBackgroundProcessCancelHandler handler) + protected void OnDeRegisterCancelHandler (IBackgroundProcessCancelHandler handler) + { + lock (_cancelHandlerList) { - lock (_cancelHandlerList) - { - _cancelHandlerList.Remove(handler); - } + _cancelHandlerList.Remove(handler); } + } - private void OnLogWindowLoad (object sender, EventArgs e) - { - PreferencesChanged(_parentLogTabWin.Preferences, true, SettingsFlags.GuiOrColors); - } + private void OnLogWindowLoad (object sender, EventArgs e) + { + PreferencesChanged(_parentLogTabWin.Preferences, true, SettingsFlags.GuiOrColors); + } - private void OnLogWindowDisposed (object sender, EventArgs e) - { - _waitingForClose = true; - _parentLogTabWin.HighlightSettingsChanged -= OnParentHighlightSettingsChanged; - _logFileReader?.DeleteAllContent(); + private void OnLogWindowDisposed (object sender, EventArgs e) + { + _waitingForClose = true; + _parentLogTabWin.HighlightSettingsChanged -= OnParentHighlightSettingsChanged; + _logFileReader?.DeleteAllContent(); - FreeFromTimeSync(); - } + FreeFromTimeSync(); + } - private void OnLogFileReaderLoadingStarted (object sender, LoadFileEventArgs e) - { - Invoke(LoadingStarted, e); - } + private void OnLogFileReaderLoadingStarted (object sender, LoadFileEventArgs e) + { + Invoke(LoadingStarted, e); + } - private void OnLogFileReaderFinishedLoading (object sender, EventArgs e) + private void OnLogFileReaderFinishedLoading (object sender, EventArgs e) + { + //Thread.CurrentThread.Name = "FinishedLoading event thread"; + _logger.Info("Finished loading."); + _isLoading = false; + _isDeadFile = false; + if (!_waitingForClose) { - //Thread.CurrentThread.Name = "FinishedLoading event thread"; - _logger.Info("Finished loading."); - _isLoading = false; - _isDeadFile = false; - if (!_waitingForClose) - { - Invoke(new MethodInvoker(LoadingFinished)); - Invoke(new MethodInvoker(LoadPersistenceData)); - Invoke(new MethodInvoker(SetGuiAfterLoading)); - _loadingFinishedEvent.Set(); - _externaLoadingFinishedEvent.Set(); - _timeSpreadCalc.SetLineCount(_logFileReader.LineCount); - - if (_reloadMemento != null) - { - Invoke(new PositionAfterReloadFx(PositionAfterReload), _reloadMemento); - } - - if (filterTailCheckBox.Checked) - { - _logger.Info("Refreshing filter view because of reload."); - Invoke(new MethodInvoker(FilterSearch)); // call on proper thread - } - - HandleChangedFilterList(); - } - - _reloadMemento = null; - } + Invoke(new MethodInvoker(LoadingFinished)); + Invoke(new MethodInvoker(LoadPersistenceData)); + Invoke(new MethodInvoker(SetGuiAfterLoading)); + _loadingFinishedEvent.Set(); + _externaLoadingFinishedEvent.Set(); + _timeSpreadCalc.SetLineCount(_logFileReader.LineCount); - private void OnLogFileReaderFileNotFound (object sender, EventArgs e) - { - if (!IsDisposed && !Disposing) + if (_reloadMemento != null) { - _logger.Info("Handling file not found event."); - _isDeadFile = true; - BeginInvoke(new MethodInvoker(LogfileDead)); + Invoke(new PositionAfterReloadFx(PositionAfterReload), _reloadMemento); } - } - - private void OnLogFileReaderRespawned (object sender, EventArgs e) - { - BeginInvoke(new MethodInvoker(LogfileRespawned)); - } - private void OnLogWindowClosing (object sender, CancelEventArgs e) - { - if (Preferences.askForClose) + if (filterTailCheckBox.Checked) { - if (MessageBox.Show("Sure to close?", "LogExpert", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) - { - e.Cancel = true; - return; - } + _logger.Info("Refreshing filter view because of reload."); + Invoke(new MethodInvoker(FilterSearch)); // call on proper thread } - SavePersistenceData(false); - CloseLogWindow(); - } - - private void OnDataGridViewColumnDividerDoubleClick (object sender, DataGridViewColumnDividerDoubleClickEventArgs e) - { - e.Handled = true; - AutoResizeColumns(dataGridView); + HandleChangedFilterList(); } - /** - * Event handler for the Load event from LogfileReader - */ - private void OnLogFileReaderLoadFile (object sender, LoadFileEventArgs e) - { - if (e.NewFile) - { - _logger.Info("File created anew."); - - // File was new created (e.g. rollover) - _isDeadFile = false; - UnRegisterLogFileReaderEvents(); - dataGridView.CurrentCellChanged -= OnDataGridViewCurrentCellChanged; - MethodInvoker invoker = ReloadNewFile; - BeginInvoke(invoker); - //Thread loadThread = new Thread(new ThreadStart(ReloadNewFile)); - //loadThread.Start(); - _logger.Debug("Reloading invoked."); - } - else if (_isLoading) - { - BeginInvoke(UpdateProgress, e); - } - } + _reloadMemento = null; + } - private void OnFileSizeChanged (object sender, LogEventArgs e) + private void OnLogFileReaderFileNotFound (object sender, EventArgs e) + { + if (!IsDisposed && !Disposing) { - //OnFileSizeChanged(e); // now done in UpdateGrid() - _logger.Info("Got FileSizeChanged event. prevLines:{0}, curr lines: {1}", e.PrevLineCount, e.LineCount); - - // - now done in the thread that works on the event args list - //if (e.IsRollover) - //{ - // ShiftBookmarks(e.RolloverOffset); - // ShiftFilterPipes(e.RolloverOffset); - //} - - //UpdateGridCallback callback = new UpdateGridCallback(UpdateGrid); - //this.BeginInvoke(callback, new object[] { e }); - lock (_logEventArgsList) - { - _logEventArgsList.Add(e); - _logEventArgsEvent.Set(); - } + _logger.Info("Handling file not found event."); + _isDeadFile = true; + BeginInvoke(new MethodInvoker(LogfileDead)); } + } - private void OnDataGridViewCellValueNeeded (object sender, DataGridViewCellValueEventArgs e) - { - var startCount = CurrentColumnizer?.GetColumnCount() ?? 0; - - e.Value = GetCellValue(e.RowIndex, e.ColumnIndex); - - // The new column could be find dynamically. - // Only support add new columns for now. - // TODO: Support reload all columns? - if (CurrentColumnizer != null && CurrentColumnizer.GetColumnCount() > startCount) - { - for (var i = startCount; i < CurrentColumnizer.GetColumnCount(); i++) - { - var colName = CurrentColumnizer.GetColumnNames()[i]; - dataGridView.Columns.Add(PaintHelper.CreateTitleColumn(colName)); - } - } - } + private void OnLogFileReaderRespawned (object sender, EventArgs e) + { + BeginInvoke(new MethodInvoker(LogfileRespawned)); + } - private void OnDataGridViewCellValuePushed (object sender, DataGridViewCellValueEventArgs e) + private void OnLogWindowClosing (object sender, CancelEventArgs e) + { + if (Preferences.askForClose) { - if (!CurrentColumnizer.IsTimeshiftImplemented()) - { - return; - } - - ILogLine line = _logFileReader.GetLogLine(e.RowIndex); - var offset = CurrentColumnizer.GetTimeOffset(); - CurrentColumnizer.SetTimeOffset(0); - ColumnizerCallbackObject.SetLineNum(e.RowIndex); - IColumnizedLogLine cols = CurrentColumnizer.SplitLine(ColumnizerCallbackObject, line); - CurrentColumnizer.SetTimeOffset(offset); - if (cols.ColumnValues.Length <= e.ColumnIndex - 2) + if (MessageBox.Show("Sure to close?", "LogExpert", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) { + e.Cancel = true; return; } - - var oldValue = cols.ColumnValues[e.ColumnIndex - 2].FullValue; - var newValue = (string)e.Value; - //string oldValue = (string) this.dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value; - CurrentColumnizer.PushValue(ColumnizerCallbackObject, e.ColumnIndex - 2, newValue, oldValue); - dataGridView.Refresh(); - TimeSpan timeSpan = new(CurrentColumnizer.GetTimeOffset() * TimeSpan.TicksPerMillisecond); - var span = timeSpan.ToString(); - var index = span.LastIndexOf('.'); - if (index > 0) - { - span = span.Substring(0, index + 4); - } - - SetTimeshiftValue(span); - SendGuiStateUpdate(); - } - - private void OnDataGridViewRowHeightInfoNeeded (object sender, DataGridViewRowHeightInfoNeededEventArgs e) - { - e.Height = GetRowHeight(e.RowIndex); } - private void OnDataGridViewCurrentCellChanged (object sender, EventArgs e) - { - if (dataGridView.CurrentRow != null) - { - _statusEventArgs.CurrentLineNum = dataGridView.CurrentRow.Index + 1; - SendStatusLineUpdate(); - if (syncFilterCheckBox.Checked) - { - SyncFilterGridPos(); - } - - if (CurrentColumnizer.IsTimeshiftImplemented() && Preferences.timestampControl) - { - SyncTimestampDisplay(); - } - - //MethodInvoker invoker = new MethodInvoker(DisplayCurrentFileOnStatusline); - //invoker.BeginInvoke(null, null); - } - } - - private void OnDataGridViewCellEndEdit (object sender, DataGridViewCellEventArgs e) - { - StatusLineText(string.Empty); - } + SavePersistenceData(false); + CloseLogWindow(); + } - private void OnEditControlKeyUp (object sender, KeyEventArgs e) - { - UpdateEditColumnDisplay((DataGridViewTextBoxEditingControl)sender); - } + private void OnDataGridViewColumnDividerDoubleClick (object sender, DataGridViewColumnDividerDoubleClickEventArgs e) + { + e.Handled = true; + AutoResizeColumns(dataGridView); + } - private void OnEditControlKeyPress (object sender, KeyPressEventArgs e) + /** + * Event handler for the Load event from LogfileReader + */ + private void OnLogFileReaderLoadFile (object sender, LoadFileEventArgs e) + { + if (e.NewFile) { - UpdateEditColumnDisplay((DataGridViewTextBoxEditingControl)sender); - } + _logger.Info("File created anew."); - private void OnEditControlClick (object sender, EventArgs e) - { - UpdateEditColumnDisplay((DataGridViewTextBoxEditingControl)sender); + // File was new created (e.g. rollover) + _isDeadFile = false; + UnRegisterLogFileReaderEvents(); + dataGridView.CurrentCellChanged -= OnDataGridViewCurrentCellChanged; + MethodInvoker invoker = ReloadNewFile; + BeginInvoke(invoker); + //Thread loadThread = new Thread(new ThreadStart(ReloadNewFile)); + //loadThread.Start(); + _logger.Debug("Reloading invoked."); } - - private void OnEditControlKeyDown (object sender, KeyEventArgs e) + else if (_isLoading) { - UpdateEditColumnDisplay((DataGridViewTextBoxEditingControl)sender); + BeginInvoke(UpdateProgress, e); } + } - private void OnDataGridViewPaint (object sender, PaintEventArgs e) - { - if (ShowBookmarkBubbles) - { - AddBookmarkOverlays(); - } - } + private void OnFileSizeChanged (object sender, LogEventArgs e) + { + //OnFileSizeChanged(e); // now done in UpdateGrid() + _logger.Info("Got FileSizeChanged event. prevLines:{0}, curr lines: {1}", e.PrevLineCount, e.LineCount); - // ====================================================================================== - // Filter Grid stuff - // ====================================================================================== + // - now done in the thread that works on the event args list + //if (e.IsRollover) + //{ + // ShiftBookmarks(e.RolloverOffset); + // ShiftFilterPipes(e.RolloverOffset); + //} - private void OnFilterSearchButtonClick (object sender, EventArgs e) + //UpdateGridCallback callback = new UpdateGridCallback(UpdateGrid); + //this.BeginInvoke(callback, new object[] { e }); + lock (_logEventArgsList) { - FilterSearch(); + _logEventArgsList.Add(e); + _logEventArgsEvent.Set(); } + } - private void OnFilterGridViewCellPainting (object sender, DataGridViewCellPaintingEventArgs e) - { - var gridView = (BufferedDataGridView)sender; - - if (e.RowIndex < 0 || e.ColumnIndex < 0 || _filterResultList.Count <= e.RowIndex) - { - e.Handled = false; - return; - } - - var lineNum = _filterResultList[e.RowIndex]; - ILogLine line = _logFileReader.GetLogLineWithWait(lineNum).Result; - - if (line != null) - { - HighlightEntry entry = FindFirstNoWordMatchHilightEntry(line); - e.Graphics.SetClip(e.CellBounds); - if ((e.State & DataGridViewElementStates.Selected) == DataGridViewElementStates.Selected) - { - Brush brush; - if (gridView.Focused) - { - brush = new SolidBrush(e.CellStyle.SelectionBackColor); - } - else - { - var color = Color.FromArgb(255, 170, 170, 170); - brush = new SolidBrush(color); - } - - e.Graphics.FillRectangle(brush, e.CellBounds); - brush.Dispose(); - } - else - { - Color bgColor = Color.White; - // paint direct filter hits with different bg color - //if (this.filterParams.SpreadEnabled && this.filterHitList.Contains(lineNum)) - //{ - // bgColor = Color.FromArgb(255, 220, 220, 220); - //} - if (!DebugOptions.DisableWordHighlight) - { - if (entry != null) - { - bgColor = entry.BackgroundColor; - } - } - else - { - if (entry != null) - { - bgColor = entry.BackgroundColor; - } - } - - e.CellStyle.BackColor = bgColor; - e.PaintBackground(e.ClipBounds, false); - } - - if (DebugOptions.DisableWordHighlight) - { - e.PaintContent(e.CellBounds); - } - else - { - PaintCell(e, filterGridView, false, entry); - } - - if (e.ColumnIndex == 0) - { - if (_bookmarkProvider.IsBookmarkAtLine(lineNum)) - { - Rectangle r = new(e.CellBounds.Left + 2, e.CellBounds.Top + 2, 6, 6); - r = e.CellBounds; - r.Inflate(-2, -2); - Brush brush = new SolidBrush(BookmarkColor); - e.Graphics.FillRectangle(brush, r); - brush.Dispose(); - - Bookmark bookmark = _bookmarkProvider.GetBookmarkForLine(lineNum); - - if (bookmark.Text.Length > 0) - { - StringFormat format = new() - { - LineAlignment = StringAlignment.Center, - Alignment = StringAlignment.Center - }; - - Brush brush2 = new SolidBrush(Color.FromArgb(255, 190, 100, 0)); - Font font = new("Verdana", Preferences.fontSize, FontStyle.Bold); - e.Graphics.DrawString("!", font, brush2, new RectangleF(r.Left, r.Top, r.Width, r.Height), format); - font.Dispose(); - brush2.Dispose(); - } - } - } + private void OnDataGridViewCellValueNeeded (object sender, DataGridViewCellValueEventArgs e) + { + var startCount = CurrentColumnizer?.GetColumnCount() ?? 0; - e.Paint(e.CellBounds, DataGridViewPaintParts.Border); - e.Handled = true; - } - } + e.Value = GetCellValue(e.RowIndex, e.ColumnIndex); - private void OnFilterGridViewCellValueNeeded (object sender, DataGridViewCellValueEventArgs e) + // The new column could be find dynamically. + // Only support add new columns for now. + // TODO: Support reload all columns? + if (CurrentColumnizer != null && CurrentColumnizer.GetColumnCount() > startCount) { - if (e.RowIndex < 0 || e.ColumnIndex < 0 || _filterResultList.Count <= e.RowIndex) + for (var i = startCount; i < CurrentColumnizer.GetColumnCount(); i++) { - e.Value = ""; - return; + var colName = CurrentColumnizer.GetColumnNames()[i]; + dataGridView.Columns.Add(PaintHelper.CreateTitleColumn(colName)); } - - var lineNum = _filterResultList[e.RowIndex]; - e.Value = GetCellValue(lineNum, e.ColumnIndex); } + } - private void OnFilterGridViewRowHeightInfoNeeded (object sender, DataGridViewRowHeightInfoNeededEventArgs e) + private void OnDataGridViewCellValuePushed (object sender, DataGridViewCellValueEventArgs e) + { + if (!CurrentColumnizer.IsTimeshiftImplemented()) { - e.Height = _lineHeight; + return; } - private void OnFilterComboBoxKeyDown (object sender, KeyEventArgs e) + ILogLine line = _logFileReader.GetLogLine(e.RowIndex); + var offset = CurrentColumnizer.GetTimeOffset(); + CurrentColumnizer.SetTimeOffset(0); + ColumnizerCallbackObject.SetLineNum(e.RowIndex); + IColumnizedLogLine cols = CurrentColumnizer.SplitLine(ColumnizerCallbackObject, line); + CurrentColumnizer.SetTimeOffset(offset); + if (cols.ColumnValues.Length <= e.ColumnIndex - 2) { - if (e.KeyCode == Keys.Enter) - { - FilterSearch(); - } + return; } - private void OnFilterGridViewColumnDividerDoubleClick (object sender, - DataGridViewColumnDividerDoubleClickEventArgs e) + var oldValue = cols.ColumnValues[e.ColumnIndex - 2].FullValue; + var newValue = (string)e.Value; + //string oldValue = (string) this.dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value; + CurrentColumnizer.PushValue(ColumnizerCallbackObject, e.ColumnIndex - 2, newValue, oldValue); + dataGridView.Refresh(); + TimeSpan timeSpan = new(CurrentColumnizer.GetTimeOffset() * TimeSpan.TicksPerMillisecond); + var span = timeSpan.ToString(); + var index = span.LastIndexOf('.'); + if (index > 0) { - e.Handled = true; - AutoResizeColumnsFx fx = AutoResizeColumns; - BeginInvoke(fx, filterGridView); + span = span.Substring(0, index + 4); } - private void OnFilterGridViewCellDoubleClick (object sender, DataGridViewCellEventArgs e) - { - if (e.ColumnIndex == 0) - { - ToggleBookmark(); - return; - } - - if (filterGridView.CurrentRow != null && e.RowIndex >= 0) - { - var lineNum = _filterResultList[filterGridView.CurrentRow.Index]; - SelectAndEnsureVisible(lineNum, true); - } - } + SetTimeshiftValue(span); + SendGuiStateUpdate(); + } - private void OnRangeCheckBoxCheckedChanged (object sender, EventArgs e) - { - filterRangeComboBox.Enabled = rangeCheckBox.Checked; - CheckForFilterDirty(); - } + private void OnDataGridViewRowHeightInfoNeeded (object sender, DataGridViewRowHeightInfoNeededEventArgs e) + { + e.Height = GetRowHeight(e.RowIndex); + } - private void OnDataGridViewScroll (object sender, ScrollEventArgs e) + private void OnDataGridViewCurrentCellChanged (object sender, EventArgs e) + { + if (dataGridView.CurrentRow != null) { - if (e.ScrollOrientation == ScrollOrientation.VerticalScroll) + _statusEventArgs.CurrentLineNum = dataGridView.CurrentRow.Index + 1; + SendStatusLineUpdate(); + if (syncFilterCheckBox.Checked) { - if (dataGridView.DisplayedRowCount(false) + dataGridView.FirstDisplayedScrollingRowIndex >= dataGridView.RowCount) - { - //this.guiStateArgs.FollowTail = true; - if (!_guiStateArgs.FollowTail) - { - FollowTailChanged(true, false); - } - - OnTailFollowed(EventArgs.Empty); - } - else - { - //this.guiStateArgs.FollowTail = false; - if (_guiStateArgs.FollowTail) - { - FollowTailChanged(false, false); - } - } - - SendGuiStateUpdate(); + SyncFilterGridPos(); } - } - private void OnFilterGridViewKeyDown (object sender, KeyEventArgs e) - { - switch (e.KeyCode) + if (CurrentColumnizer.IsTimeshiftImplemented() && Preferences.timestampControl) { - case Keys.Enter: - { - if (filterGridView.CurrentCellAddress.Y >= 0 && filterGridView.CurrentCellAddress.Y < _filterResultList.Count) - { - var lineNum = _filterResultList[filterGridView.CurrentCellAddress.Y]; - SelectLine(lineNum, false, true); - e.Handled = true; - } - - break; - } - case Keys.Tab when e.Modifiers == Keys.None: - dataGridView.Focus(); - e.Handled = true; - break; + SyncTimestampDisplay(); } - } - private void OnDataGridViewKeyDown (object sender, KeyEventArgs e) - { - switch (e.KeyCode) - { - case Keys.Tab when e.Modifiers == Keys.None: - { - filterGridView.Focus(); - e.Handled = true; - break; - } - } + //MethodInvoker invoker = new MethodInvoker(DisplayCurrentFileOnStatusline); + //invoker.BeginInvoke(null, null); + } + } - //switch (e.KeyCode) - //{ - // case Keys.Tab when e.Modifiers == Keys.Control: - // //this.parentLogTabWin.SwitchTab(e.Shift); - // break; - //} + private void OnDataGridViewCellEndEdit (object sender, DataGridViewCellEventArgs e) + { + StatusLineText(string.Empty); + } - _shouldCallTimeSync = true; - } + private void OnEditControlKeyUp (object sender, KeyEventArgs e) + { + UpdateEditColumnDisplay((DataGridViewTextBoxEditingControl)sender); + } - private void OnDataGridViewPreviewKeyDown (object sender, PreviewKeyDownEventArgs e) - { - if (e.KeyCode == Keys.Tab && e.Control) - { - e.IsInputKey = true; - } - } + private void OnEditControlKeyPress (object sender, KeyPressEventArgs e) + { + UpdateEditColumnDisplay((DataGridViewTextBoxEditingControl)sender); + } - private void OnDataGridViewCellContentDoubleClick (object sender, DataGridViewCellEventArgs e) - { - if (dataGridView.CurrentCell != null) - { - dataGridView.BeginEdit(false); - } - } + private void OnEditControlClick (object sender, EventArgs e) + { + UpdateEditColumnDisplay((DataGridViewTextBoxEditingControl)sender); + } - private void OnSyncFilterCheckBoxCheckedChanged (object sender, EventArgs e) - { - if (syncFilterCheckBox.Checked) - { - SyncFilterGridPos(); - } - } + private void OnEditControlKeyDown (object sender, KeyEventArgs e) + { + UpdateEditColumnDisplay((DataGridViewTextBoxEditingControl)sender); + } - private void OnDataGridViewLeave (object sender, EventArgs e) + private void OnDataGridViewPaint (object sender, PaintEventArgs e) + { + if (ShowBookmarkBubbles) { - InvalidateCurrentRow(dataGridView); + AddBookmarkOverlays(); } + } - private void OnDataGridViewEnter (object sender, EventArgs e) - { - InvalidateCurrentRow(dataGridView); - } + // ====================================================================================== + // Filter Grid stuff + // ====================================================================================== - private void OnFilterGridViewEnter (object sender, EventArgs e) - { - InvalidateCurrentRow(filterGridView); - } + private void OnFilterSearchButtonClick (object sender, EventArgs e) + { + FilterSearch(); + } - private void OnFilterGridViewLeave (object sender, EventArgs e) - { - InvalidateCurrentRow(filterGridView); - } + private void OnFilterGridViewCellPainting (object sender, DataGridViewCellPaintingEventArgs e) + { + var gridView = (BufferedDataGridView)sender; - private void OnDataGridViewResize (object sender, EventArgs e) + if (e.RowIndex < 0 || e.ColumnIndex < 0 || _filterResultList.Count <= e.RowIndex) { - if (_logFileReader != null && dataGridView.RowCount > 0 && _guiStateArgs.FollowTail) - { - dataGridView.FirstDisplayedScrollingRowIndex = dataGridView.RowCount - 1; - } + e.Handled = false; + return; } - private void OnDataGridViewSelectionChanged (object sender, EventArgs e) - { - UpdateSelectionDisplay(); - } + var lineNum = _filterResultList[e.RowIndex]; + ILogLine line = _logFileReader.GetLogLineWithWait(lineNum).Result; - private void OnSelectionChangedTriggerSignal (object sender, EventArgs e) + if (line != null) { - var selCount = 0; - try + HighlightEntry entry = FindFirstNoWordMatchHilightEntry(line); + e.Graphics.SetClip(e.CellBounds); + if ((e.State & DataGridViewElementStates.Selected) == DataGridViewElementStates.Selected) { - _logger.Debug("Selection changed trigger"); - selCount = dataGridView.SelectedRows.Count; - if (selCount > 1) + Brush brush; + if (gridView.Focused) { - StatusLineText(selCount + " selected lines"); + brush = new SolidBrush(e.CellStyle.SelectionBackColor); } else { - if (IsMultiFile) - { - MethodInvoker invoker = DisplayCurrentFileOnStatusline; - invoker.BeginInvoke(null, null); - } - else - { - StatusLineText(""); - } + var color = Color.FromArgb(255, 170, 170, 170); + brush = new SolidBrush(color); } - } - catch (Exception ex) - { - _logger.Error(ex, "Error in selectionChangedTrigger_Signal selcount {0}", selCount); - } - } - - private void OnFilterKnobControlValueChanged (object sender, EventArgs e) - { - CheckForFilterDirty(); - } - private void OnFilterToTabButtonClick (object sender, EventArgs e) - { - FilterToTab(); - } - - private void OnPipeDisconnected (object sender, EventArgs e) - { - if (sender.GetType() == typeof(FilterPipe)) - { - lock (_filterPipeList) - { - _filterPipeList.Remove((FilterPipe)sender); - if (_filterPipeList.Count == 0) - // reset naming counter to 0 if no more open filter tabs for this source window - { - _filterPipeNameCounter = 0; - } - } + e.Graphics.FillRectangle(brush, e.CellBounds); + brush.Dispose(); } - } - - private void OnAdvancedButtonClick (object sender, EventArgs e) - { - _showAdvanced = !_showAdvanced; - ShowAdvancedFilterPanel(_showAdvanced); - } - - private void OnFilterSplitContainerMouseDown (object sender, MouseEventArgs e) - { - ((SplitContainer)sender).IsSplitterFixed = true; - } - - private void OnFilterSplitContainerMouseUp (object sender, MouseEventArgs e) - { - ((SplitContainer)sender).IsSplitterFixed = false; - } - - private void OnFilterSplitContainerMouseMove (object sender, MouseEventArgs e) - { - var splitContainer = (SplitContainer)sender; - if (splitContainer.IsSplitterFixed) + else { - if (e.Button.Equals(MouseButtons.Left)) + Color bgColor = Color.White; + // paint direct filter hits with different bg color + //if (this.filterParams.SpreadEnabled && this.filterHitList.Contains(lineNum)) + //{ + // bgColor = Color.FromArgb(255, 220, 220, 220); + //} + if (!DebugOptions.DisableWordHighlight) { - if (splitContainer.Orientation.Equals(Orientation.Vertical)) + if (entry != null) { - if (e.X > 0 && e.X < splitContainer.Width) - { - splitContainer.SplitterDistance = e.X; - splitContainer.Refresh(); - } - } - else - { - if (e.Y > 0 && e.Y < splitContainer.Height) - { - splitContainer.SplitterDistance = e.Y; - splitContainer.Refresh(); - } + bgColor = entry.BackgroundColor; } } else { - splitContainer.IsSplitterFixed = false; + if (entry != null) + { + bgColor = entry.BackgroundColor; + } } - } - } - - private void OnFilterSplitContainerMouseDoubleClick (object sender, MouseEventArgs e) - { - AutoResizeFilterBox(); - } - - #region Context Menu - - private void OnDataGridContextMenuStripOpening (object sender, CancelEventArgs e) - { - var lineNum = -1; - if (dataGridView.CurrentRow != null) - { - lineNum = dataGridView.CurrentRow.Index; + + e.CellStyle.BackColor = bgColor; + e.PaintBackground(e.ClipBounds, false); } - if (lineNum == -1) + if (DebugOptions.DisableWordHighlight) { - return; + e.PaintContent(e.CellBounds); } - - var refLineNum = lineNum; - - copyToTabToolStripMenuItem.Enabled = dataGridView.SelectedCells.Count > 0; - scrollAllTabsToTimestampToolStripMenuItem.Enabled = CurrentColumnizer.IsTimeshiftImplemented() - && - GetTimestampForLine(ref refLineNum, false) != - DateTime.MinValue; - - locateLineInOriginalFileToolStripMenuItem.Enabled = IsTempFile && - FilterPipe != null && - FilterPipe.GetOriginalLineNum(lineNum) != -1; - - markEditModeToolStripMenuItem.Enabled = !dataGridView.CurrentCell.ReadOnly; - - // Remove all "old" plugin entries - var index = dataGridContextMenuStrip.Items.IndexOf(pluginSeparator); - - if (index > 0) + else { - for (var i = index + 1; i < dataGridContextMenuStrip.Items.Count;) - { - dataGridContextMenuStrip.Items.RemoveAt(i); - } + PaintCell(e, filterGridView, false, entry); } - // Add plugin entries - var isAdded = false; - if (PluginRegistry.PluginRegistry.Instance.RegisteredContextMenuPlugins.Count > 0) + if (e.ColumnIndex == 0) { - IList lines = GetSelectedContent(); - foreach (IContextMenuEntry entry in PluginRegistry.PluginRegistry.Instance.RegisteredContextMenuPlugins) + if (_bookmarkProvider.IsBookmarkAtLine(lineNum)) { - LogExpertCallback callback = new(this); - var menuText = entry.GetMenuText(lines.Count, CurrentColumnizer, callback.GetLogLine(lines[0])); + Rectangle r = new(e.CellBounds.Left + 2, e.CellBounds.Top + 2, 6, 6); + r = e.CellBounds; + r.Inflate(-2, -2); + Brush brush = new SolidBrush(BookmarkColor); + e.Graphics.FillRectangle(brush, r); + brush.Dispose(); + + Bookmark bookmark = _bookmarkProvider.GetBookmarkForLine(lineNum); - if (menuText != null) + if (bookmark.Text.Length > 0) { - var disabled = menuText.StartsWith('_'); - if (disabled) + StringFormat format = new() { - menuText = menuText[1..]; - } - - ToolStripItem item = dataGridContextMenuStrip.Items.Add(menuText, null, OnHandlePluginContextMenu); - item.Tag = new ContextMenuPluginEventArgs(entry, lines, CurrentColumnizer, callback); - item.Enabled = !disabled; - isAdded = true; + LineAlignment = StringAlignment.Center, + Alignment = StringAlignment.Center + }; + + Brush brush2 = new SolidBrush(Color.FromArgb(255, 190, 100, 0)); + Font font = new("Verdana", Preferences.fontSize, FontStyle.Bold); + e.Graphics.DrawString("!", font, brush2, new RectangleF(r.Left, r.Top, r.Width, r.Height), format); + font.Dispose(); + brush2.Dispose(); } } } - pluginSeparator.Visible = isAdded; + e.Paint(e.CellBounds, DataGridViewPaintParts.Border); + e.Handled = true; + } + } - // enable/disable Temp Highlight item - tempHighlightsToolStripMenuItem.Enabled = _tempHighlightEntryList.Count > 0; + private void OnFilterGridViewCellValueNeeded (object sender, DataGridViewCellValueEventArgs e) + { + if (e.RowIndex < 0 || e.ColumnIndex < 0 || _filterResultList.Count <= e.RowIndex) + { + e.Value = ""; + return; + } - markCurrentFilterRangeToolStripMenuItem.Enabled = string.IsNullOrEmpty(filterRangeComboBox.Text) == false; + var lineNum = _filterResultList[e.RowIndex]; + e.Value = GetCellValue(lineNum, e.ColumnIndex); + } - if (CurrentColumnizer.IsTimeshiftImplemented()) - { - IList list = _parentLogTabWin.GetListOfOpenFiles(); - syncTimestampsToToolStripMenuItem.Enabled = true; - syncTimestampsToToolStripMenuItem.DropDownItems.Clear(); - EventHandler ev = OnHandleSyncContextMenu; - Font italicFont = new(syncTimestampsToToolStripMenuItem.Font.FontFamily, syncTimestampsToToolStripMenuItem.Font.Size, FontStyle.Italic); + private void OnFilterGridViewRowHeightInfoNeeded (object sender, DataGridViewRowHeightInfoNeededEventArgs e) + { + e.Height = _lineHeight; + } - foreach (WindowFileEntry fileEntry in list) - { - if (fileEntry.LogWindow != this) - { - var item = syncTimestampsToToolStripMenuItem.DropDownItems.Add(fileEntry.Title, null, ev) as ToolStripMenuItem; - item.Tag = fileEntry; - item.Checked = TimeSyncList != null && TimeSyncList.Contains(fileEntry.LogWindow); - if (fileEntry.LogWindow.TimeSyncList != null && !fileEntry.LogWindow.TimeSyncList.Contains(this)) - { - item.Font = italicFont; - item.ForeColor = Color.Blue; - } + private void OnFilterComboBoxKeyDown (object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Enter) + { + FilterSearch(); + } + } - item.Enabled = fileEntry.LogWindow.CurrentColumnizer.IsTimeshiftImplemented(); - } - } - } - else - { - syncTimestampsToToolStripMenuItem.Enabled = false; - } + private void OnFilterGridViewColumnDividerDoubleClick (object sender, + DataGridViewColumnDividerDoubleClickEventArgs e) + { + e.Handled = true; + AutoResizeColumnsFx fx = AutoResizeColumns; + BeginInvoke(fx, filterGridView); + } - freeThisWindowFromTimeSyncToolStripMenuItem.Enabled = TimeSyncList != null && - TimeSyncList.Count > 1; + private void OnFilterGridViewCellDoubleClick (object sender, DataGridViewCellEventArgs e) + { + if (e.ColumnIndex == 0) + { + ToggleBookmark(); + return; } - private void OnHandlePluginContextMenu (object sender, EventArgs args) + if (filterGridView.CurrentRow != null && e.RowIndex >= 0) { - if (sender is ToolStripItem item) - { - var menuArgs = item.Tag as ContextMenuPluginEventArgs; - var logLines = menuArgs.LogLines; - menuArgs.Entry.MenuSelected(logLines.Count, menuArgs.Columnizer, menuArgs.Callback.GetLogLine(logLines[0])); - } + var lineNum = _filterResultList[filterGridView.CurrentRow.Index]; + SelectAndEnsureVisible(lineNum, true); } + } + + private void OnRangeCheckBoxCheckedChanged (object sender, EventArgs e) + { + filterRangeComboBox.Enabled = rangeCheckBox.Checked; + CheckForFilterDirty(); + } - private void OnHandleSyncContextMenu (object sender, EventArgs args) + private void OnDataGridViewScroll (object sender, ScrollEventArgs e) + { + if (e.ScrollOrientation == ScrollOrientation.VerticalScroll) { - if (sender is ToolStripItem item) + if (dataGridView.DisplayedRowCount(false) + dataGridView.FirstDisplayedScrollingRowIndex >= dataGridView.RowCount) { - var entry = item.Tag as WindowFileEntry; - - if (TimeSyncList != null && TimeSyncList.Contains(entry.LogWindow)) + //this.guiStateArgs.FollowTail = true; + if (!_guiStateArgs.FollowTail) { - FreeSlaveFromTimesync(entry.LogWindow); + FollowTailChanged(true, false); } - else - //AddSlaveToTimesync(entry.LogWindow); + + OnTailFollowed(EventArgs.Empty); + } + else + { + //this.guiStateArgs.FollowTail = false; + if (_guiStateArgs.FollowTail) { - AddOtherWindowToTimesync(entry.LogWindow); + FollowTailChanged(false, false); } } - } - - private void OnCopyToolStripMenuItemClick (object sender, EventArgs e) - { - CopyMarkedLinesToClipboard(); - } - private void OnCopyToTabToolStripMenuItemClick (object sender, EventArgs e) - { - CopyMarkedLinesToTab(); + SendGuiStateUpdate(); } + } - private void OnScrollAllTabsToTimestampToolStripMenuItemClick (object sender, EventArgs e) + private void OnFilterGridViewKeyDown (object sender, KeyEventArgs e) + { + switch (e.KeyCode) { - if (CurrentColumnizer.IsTimeshiftImplemented()) - { - var currentLine = dataGridView.CurrentCellAddress.Y; - if (currentLine > 0 && currentLine < dataGridView.RowCount) + case Keys.Enter: { - var lineNum = currentLine; - DateTime timeStamp = GetTimestampForLine(ref lineNum, false); - if (timeStamp.Equals(DateTime.MinValue)) // means: invalid + if (filterGridView.CurrentCellAddress.Y >= 0 && filterGridView.CurrentCellAddress.Y < _filterResultList.Count) { - return; + var lineNum = _filterResultList[filterGridView.CurrentCellAddress.Y]; + SelectLine(lineNum, false, true); + e.Handled = true; } - _parentLogTabWin.ScrollAllTabsToTimestamp(timeStamp, this); + break; } - } + case Keys.Tab when e.Modifiers == Keys.None: + dataGridView.Focus(); + e.Handled = true; + break; } + } - private void OnLocateLineInOriginalFileToolStripMenuItemClick (object sender, EventArgs e) + private void OnDataGridViewKeyDown (object sender, KeyEventArgs e) + { + switch (e.KeyCode) { - if (dataGridView.CurrentRow != null && FilterPipe != null) - { - var lineNum = FilterPipe.GetOriginalLineNum(dataGridView.CurrentRow.Index); - if (lineNum != -1) + case Keys.Tab when e.Modifiers == Keys.None: { - FilterPipe.LogWindow.SelectLine(lineNum, false, true); - _parentLogTabWin.SelectTab(FilterPipe.LogWindow); + filterGridView.Focus(); + e.Handled = true; + break; } - } } - private void OnToggleBoomarkToolStripMenuItemClick (object sender, EventArgs e) + //switch (e.KeyCode) + //{ + // case Keys.Tab when e.Modifiers == Keys.Control: + // //this.parentLogTabWin.SwitchTab(e.Shift); + // break; + //} + + _shouldCallTimeSync = true; + } + + private void OnDataGridViewPreviewKeyDown (object sender, PreviewKeyDownEventArgs e) + { + if (e.KeyCode == Keys.Tab && e.Control) + { + e.IsInputKey = true; + } + } + + private void OnDataGridViewCellContentDoubleClick (object sender, DataGridViewCellEventArgs e) + { + if (dataGridView.CurrentCell != null) { - ToggleBookmark(); + dataGridView.BeginEdit(false); } + } - private void OnMarkEditModeToolStripMenuItemClick (object sender, EventArgs e) + private void OnSyncFilterCheckBoxCheckedChanged (object sender, EventArgs e) + { + if (syncFilterCheckBox.Checked) { - StartEditMode(); + SyncFilterGridPos(); } + } + + private void OnDataGridViewLeave (object sender, EventArgs e) + { + InvalidateCurrentRow(dataGridView); + } + + private void OnDataGridViewEnter (object sender, EventArgs e) + { + InvalidateCurrentRow(dataGridView); + } + + private void OnFilterGridViewEnter (object sender, EventArgs e) + { + InvalidateCurrentRow(filterGridView); + } + + private void OnFilterGridViewLeave (object sender, EventArgs e) + { + InvalidateCurrentRow(filterGridView); + } - private void OnLogWindowSizeChanged (object sender, EventArgs e) + private void OnDataGridViewResize (object sender, EventArgs e) + { + if (_logFileReader != null && dataGridView.RowCount > 0 && _guiStateArgs.FollowTail) { - //AdjustMinimumGridWith(); - AdjustHighlightSplitterWidth(); + dataGridView.FirstDisplayedScrollingRowIndex = dataGridView.RowCount - 1; } + } - #region BookMarkList + private void OnDataGridViewSelectionChanged (object sender, EventArgs e) + { + UpdateSelectionDisplay(); + } - private void OnColumnRestrictCheckBoxCheckedChanged (object sender, EventArgs e) + private void OnSelectionChangedTriggerSignal (object sender, EventArgs e) + { + var selCount = 0; + try { - columnButton.Enabled = columnRestrictCheckBox.Checked; - if (columnRestrictCheckBox.Checked) // disable when nothing to filter + _logger.Debug("Selection changed trigger"); + selCount = dataGridView.SelectedRows.Count; + if (selCount > 1) { - columnNamesLabel.Visible = true; - _filterParams.ColumnRestrict = true; - columnNamesLabel.Text = CalculateColumnNames(_filterParams); + StatusLineText(selCount + " selected lines"); } else { - columnNamesLabel.Visible = false; + if (IsMultiFile) + { + MethodInvoker invoker = DisplayCurrentFileOnStatusline; + invoker.BeginInvoke(null, null); + } + else + { + StatusLineText(""); + } } - - CheckForFilterDirty(); } + catch (Exception ex) + { + _logger.Error(ex, "Error in selectionChangedTrigger_Signal selcount {0}", selCount); + } + } + + private void OnFilterKnobControlValueChanged (object sender, EventArgs e) + { + CheckForFilterDirty(); + } + + private void OnFilterToTabButtonClick (object sender, EventArgs e) + { + FilterToTab(); + } - private void OnColumnButtonClick (object sender, EventArgs e) + private void OnPipeDisconnected (object sender, EventArgs e) + { + if (sender.GetType() == typeof(FilterPipe)) { - _filterParams.CurrentColumnizer = _currentColumnizer; - FilterColumnChooser chooser = new(_filterParams); - if (chooser.ShowDialog() == DialogResult.OK) + lock (_filterPipeList) { - columnNamesLabel.Text = CalculateColumnNames(_filterParams); - - //CheckForFilterDirty(); //!!!GBro: Indicate to redo the search if search columns were changed - filterSearchButton.Image = _searchButtonImage; - saveFilterButton.Enabled = false; + _filterPipeList.Remove((FilterPipe)sender); + if (_filterPipeList.Count == 0) + // reset naming counter to 0 if no more open filter tabs for this source window + { + _filterPipeNameCounter = 0; + } } } + } + + private void OnAdvancedButtonClick (object sender, EventArgs e) + { + _showAdvanced = !_showAdvanced; + ShowAdvancedFilterPanel(_showAdvanced); + } - #endregion + private void OnFilterSplitContainerMouseDown (object sender, MouseEventArgs e) + { + ((SplitContainer)sender).IsSplitterFixed = true; + } - #region Column Header Context Menu + private void OnFilterSplitContainerMouseUp (object sender, MouseEventArgs e) + { + ((SplitContainer)sender).IsSplitterFixed = false; + } - private void OnDataGridViewCellContextMenuStripNeeded (object sender, DataGridViewCellContextMenuStripNeededEventArgs e) + private void OnFilterSplitContainerMouseMove (object sender, MouseEventArgs e) + { + var splitContainer = (SplitContainer)sender; + if (splitContainer.IsSplitterFixed) { - if (e.RowIndex >= 0 && e.RowIndex < dataGridView.RowCount && !dataGridView.Rows[e.RowIndex].Selected) - { - SelectLine(e.RowIndex, false, true); - } - else if (e.RowIndex < 0) + if (e.Button.Equals(MouseButtons.Left)) { - e.ContextMenuStrip = columnContextMenuStrip; + if (splitContainer.Orientation.Equals(Orientation.Vertical)) + { + if (e.X > 0 && e.X < splitContainer.Width) + { + splitContainer.SplitterDistance = e.X; + splitContainer.Refresh(); + } + } + else + { + if (e.Y > 0 && e.Y < splitContainer.Height) + { + splitContainer.SplitterDistance = e.Y; + splitContainer.Refresh(); + } + } } - - if (e.ContextMenuStrip == columnContextMenuStrip) + else { - _selectedCol = e.ColumnIndex; + splitContainer.IsSplitterFixed = false; } } + } - //private void boomarkDataGridView_CellContextMenuStripNeeded(object sender, DataGridViewCellContextMenuStripNeededEventArgs e) - //{ - // if (e.RowIndex > 0 && e.RowIndex < this.boomarkDataGridView.RowCount - // && !this.boomarkDataGridView.Rows[e.RowIndex].Selected) - // { - // this.boomarkDataGridView.Rows[e.RowIndex].Selected = true; - // this.boomarkDataGridView.CurrentCell = this.boomarkDataGridView.Rows[e.RowIndex].Cells[0]; - // } - // if (e.ContextMenuStrip == this.columnContextMenuStrip) - // { - // this.selectedCol = e.ColumnIndex; - // } - //} + private void OnFilterSplitContainerMouseDoubleClick (object sender, MouseEventArgs e) + { + AutoResizeFilterBox(); + } - private void OnFilterGridViewCellContextMenuStripNeeded (object sender, DataGridViewCellContextMenuStripNeededEventArgs e) + #region Context Menu + + private void OnDataGridContextMenuStripOpening (object sender, CancelEventArgs e) + { + var lineNum = -1; + if (dataGridView.CurrentRow != null) { - if (e.ContextMenuStrip == columnContextMenuStrip) - { - _selectedCol = e.ColumnIndex; - } + lineNum = dataGridView.CurrentRow.Index; } - private void OnColumnContextMenuStripOpening (object sender, CancelEventArgs e) + if (lineNum == -1) { - Control ctl = columnContextMenuStrip.SourceControl; - var gridView = ctl as BufferedDataGridView; - var frozen = false; - if (_freezeStateMap.TryGetValue(ctl, out var value)) - { - frozen = value; - } + return; + } - freezeLeftColumnsUntilHereToolStripMenuItem.Checked = frozen; + var refLineNum = lineNum; - if (frozen) - { - freezeLeftColumnsUntilHereToolStripMenuItem.Text = "Frozen"; - } - else - { - if (ctl is BufferedDataGridView) - { - freezeLeftColumnsUntilHereToolStripMenuItem.Text = $"Freeze left columns until here ({gridView.Columns[_selectedCol].HeaderText})"; - } - } + copyToTabToolStripMenuItem.Enabled = dataGridView.SelectedCells.Count > 0; + scrollAllTabsToTimestampToolStripMenuItem.Enabled = CurrentColumnizer.IsTimeshiftImplemented() + && + GetTimestampForLine(ref refLineNum, false) != + DateTime.MinValue; + locateLineInOriginalFileToolStripMenuItem.Enabled = IsTempFile && + FilterPipe != null && + FilterPipe.GetOriginalLineNum(lineNum) != -1; - DataGridViewColumn col = gridView.Columns[_selectedCol]; - moveLeftToolStripMenuItem.Enabled = col != null && col.DisplayIndex > 0; - moveRightToolStripMenuItem.Enabled = col != null && col.DisplayIndex < gridView.Columns.Count - 1; + markEditModeToolStripMenuItem.Enabled = !dataGridView.CurrentCell.ReadOnly; - if (gridView.Columns.Count - 1 > _selectedCol) + // Remove all "old" plugin entries + var index = dataGridContextMenuStrip.Items.IndexOf(pluginSeparator); + + if (index > 0) + { + for (var i = index + 1; i < dataGridContextMenuStrip.Items.Count;) { - // DataGridViewColumn colRight = gridView.Columns[this.selectedCol + 1]; - DataGridViewColumn colRight = gridView.Columns.GetNextColumn(col, DataGridViewElementStates.None, DataGridViewElementStates.None); - moveRightToolStripMenuItem.Enabled = colRight != null && colRight.Frozen == col.Frozen; + dataGridContextMenuStrip.Items.RemoveAt(i); } + } - if (_selectedCol > 0) + // Add plugin entries + var isAdded = false; + if (PluginRegistry.PluginRegistry.Instance.RegisteredContextMenuPlugins.Count > 0) + { + IList lines = GetSelectedContent(); + foreach (IContextMenuEntry entry in PluginRegistry.PluginRegistry.Instance.RegisteredContextMenuPlugins) { - //DataGridViewColumn colLeft = gridView.Columns[this.selectedCol - 1]; - DataGridViewColumn colLeft = gridView.Columns.GetPreviousColumn(col, DataGridViewElementStates.None, DataGridViewElementStates.None); + LogExpertCallback callback = new(this); + var menuText = entry.GetMenuText(lines.Count, CurrentColumnizer, callback.GetLogLine(lines[0])); + + if (menuText != null) + { + var disabled = menuText.StartsWith('_'); + if (disabled) + { + menuText = menuText[1..]; + } - moveLeftToolStripMenuItem.Enabled = colLeft != null && colLeft.Frozen == col.Frozen; + ToolStripItem item = dataGridContextMenuStrip.Items.Add(menuText, null, OnHandlePluginContextMenu); + item.Tag = new ContextMenuPluginEventArgs(entry, lines, CurrentColumnizer, callback); + item.Enabled = !disabled; + isAdded = true; + } } + } - DataGridViewColumn colLast = gridView.Columns[gridView.Columns.Count - 1]; - moveToLastColumnToolStripMenuItem.Enabled = colLast != null && colLast.Frozen == col.Frozen; + pluginSeparator.Visible = isAdded; + + // enable/disable Temp Highlight item + tempHighlightsToolStripMenuItem.Enabled = _tempHighlightEntryList.Count > 0; + + markCurrentFilterRangeToolStripMenuItem.Enabled = string.IsNullOrEmpty(filterRangeComboBox.Text) == false; + + if (CurrentColumnizer.IsTimeshiftImplemented()) + { + IList list = _parentLogTabWin.GetListOfOpenFiles(); + syncTimestampsToToolStripMenuItem.Enabled = true; + syncTimestampsToToolStripMenuItem.DropDownItems.Clear(); + EventHandler ev = OnHandleSyncContextMenu; + Font italicFont = new(syncTimestampsToToolStripMenuItem.Font.FontFamily, syncTimestampsToToolStripMenuItem.Font.Size, FontStyle.Italic); - // Fill context menu with column names - // - EventHandler ev = OnHandleColumnItemContextMenu; - allColumnsToolStripMenuItem.DropDownItems.Clear(); - foreach (DataGridViewColumn column in gridView.Columns) + foreach (WindowFileEntry fileEntry in list) { - if (column.HeaderText.Length > 0) + if (fileEntry.LogWindow != this) { - var item = allColumnsToolStripMenuItem.DropDownItems.Add(column.HeaderText, null, ev) as ToolStripMenuItem; - item.Tag = column; - item.Enabled = !column.Frozen; + var item = syncTimestampsToToolStripMenuItem.DropDownItems.Add(fileEntry.Title, null, ev) as ToolStripMenuItem; + item.Tag = fileEntry; + item.Checked = TimeSyncList != null && TimeSyncList.Contains(fileEntry.LogWindow); + if (fileEntry.LogWindow.TimeSyncList != null && !fileEntry.LogWindow.TimeSyncList.Contains(this)) + { + item.Font = italicFont; + item.ForeColor = Color.Blue; + } + + item.Enabled = fileEntry.LogWindow.CurrentColumnizer.IsTimeshiftImplemented(); } } } + else + { + syncTimestampsToToolStripMenuItem.Enabled = false; + } + + freeThisWindowFromTimeSyncToolStripMenuItem.Enabled = TimeSyncList != null && + TimeSyncList.Count > 1; + } - private void OnHandleColumnItemContextMenu (object sender, EventArgs args) + private void OnHandlePluginContextMenu (object sender, EventArgs args) + { + if (sender is ToolStripItem item) { - if (sender is ToolStripItem item) - { - var column = item.Tag as DataGridViewColumn; - column.Visible = true; - column.DataGridView.FirstDisplayedScrollingColumnIndex = column.Index; - } + var menuArgs = item.Tag as ContextMenuPluginEventArgs; + var logLines = menuArgs.LogLines; + menuArgs.Entry.MenuSelected(logLines.Count, menuArgs.Columnizer, menuArgs.Callback.GetLogLine(logLines[0])); } + } - private void OnFreezeLeftColumnsUntilHereToolStripMenuItemClick (object sender, EventArgs e) + private void OnHandleSyncContextMenu (object sender, EventArgs args) + { + if (sender is ToolStripItem item) { - Control ctl = columnContextMenuStrip.SourceControl; - var frozen = false; + var entry = item.Tag as WindowFileEntry; - if (_freezeStateMap.TryGetValue(ctl, out var value)) + if (TimeSyncList != null && TimeSyncList.Contains(entry.LogWindow)) { - frozen = value; + FreeSlaveFromTimesync(entry.LogWindow); } - - frozen = !frozen; - _freezeStateMap[ctl] = frozen; - - if (ctl is BufferedDataGridView gridView) + else + //AddSlaveToTimesync(entry.LogWindow); { - ApplyFrozenState(gridView); + AddOtherWindowToTimesync(entry.LogWindow); } } + } - private void OnMoveToLastColumnToolStripMenuItemClick (object sender, EventArgs e) - { - var gridView = columnContextMenuStrip.SourceControl as BufferedDataGridView; - DataGridViewColumn col = gridView.Columns[_selectedCol]; - if (col != null) - { - col.DisplayIndex = gridView.Columns.Count - 1; - } - } + private void OnCopyToolStripMenuItemClick (object sender, EventArgs e) + { + CopyMarkedLinesToClipboard(); + } + + private void OnCopyToTabToolStripMenuItemClick (object sender, EventArgs e) + { + CopyMarkedLinesToTab(); + } - private void OnMoveLeftToolStripMenuItemClick (object sender, EventArgs e) + private void OnScrollAllTabsToTimestampToolStripMenuItemClick (object sender, EventArgs e) + { + if (CurrentColumnizer.IsTimeshiftImplemented()) { - var gridView = columnContextMenuStrip.SourceControl as BufferedDataGridView; - DataGridViewColumn col = gridView.Columns[_selectedCol]; - if (col != null && col.DisplayIndex > 0) + var currentLine = dataGridView.CurrentCellAddress.Y; + if (currentLine > 0 && currentLine < dataGridView.RowCount) { - col.DisplayIndex -= 1; + var lineNum = currentLine; + DateTime timeStamp = GetTimestampForLine(ref lineNum, false); + if (timeStamp.Equals(DateTime.MinValue)) // means: invalid + { + return; + } + + _parentLogTabWin.ScrollAllTabsToTimestamp(timeStamp, this); } } + } - private void OnMoveRightToolStripMenuItemClick (object sender, EventArgs e) + private void OnLocateLineInOriginalFileToolStripMenuItemClick (object sender, EventArgs e) + { + if (dataGridView.CurrentRow != null && FilterPipe != null) { - var gridView = columnContextMenuStrip.SourceControl as BufferedDataGridView; - DataGridViewColumn col = gridView.Columns[_selectedCol]; - if (col != null && col.DisplayIndex < gridView.Columns.Count - 1) + var lineNum = FilterPipe.GetOriginalLineNum(dataGridView.CurrentRow.Index); + if (lineNum != -1) { - col.DisplayIndex = col.DisplayIndex + 1; + FilterPipe.LogWindow.SelectLine(lineNum, false, true); + _parentLogTabWin.SelectTab(FilterPipe.LogWindow); } } + } - private void OnHideColumnToolStripMenuItemClick (object sender, EventArgs e) - { - var gridView = columnContextMenuStrip.SourceControl as BufferedDataGridView; - DataGridViewColumn col = gridView.Columns[_selectedCol]; - col.Visible = false; - } + private void OnToggleBoomarkToolStripMenuItemClick (object sender, EventArgs e) + { + ToggleBookmark(); + } - private void OnRestoreColumnsToolStripMenuItemClick (object sender, EventArgs e) - { - var gridView = columnContextMenuStrip.SourceControl as BufferedDataGridView; - foreach (DataGridViewColumn col in gridView.Columns) - { - col.Visible = true; - } - } + private void OnMarkEditModeToolStripMenuItemClick (object sender, EventArgs e) + { + StartEditMode(); + } + + private void OnLogWindowSizeChanged (object sender, EventArgs e) + { + //AdjustMinimumGridWith(); + AdjustHighlightSplitterWidth(); + } - private void OnTimeSpreadingControlLineSelected (object sender, SelectLineEventArgs e) + #region BookMarkList + + private void OnColumnRestrictCheckBoxCheckedChanged (object sender, EventArgs e) + { + columnButton.Enabled = columnRestrictCheckBox.Checked; + if (columnRestrictCheckBox.Checked) // disable when nothing to filter { - SelectLine(e.Line, false, true); + columnNamesLabel.Visible = true; + _filterParams.ColumnRestrict = true; + columnNamesLabel.Text = CalculateColumnNames(_filterParams); } - - private void OnBookmarkCommentToolStripMenuItemClick (object sender, EventArgs e) + else { - AddBookmarkAndEditComment(); + columnNamesLabel.Visible = false; } - private void OnHighlightSelectionInLogFileToolStripMenuItemClick (object sender, EventArgs e) + CheckForFilterDirty(); + } + + private void OnColumnButtonClick (object sender, EventArgs e) + { + _filterParams.CurrentColumnizer = _currentColumnizer; + FilterColumnChooser chooser = new(_filterParams); + if (chooser.ShowDialog() == DialogResult.OK) { - if (dataGridView.EditingControl is DataGridViewTextBoxEditingControl ctl) - { - var he = new HighlightEntry() - { - SearchText = ctl.SelectedText, - ForegroundColor = Color.Red, - BackgroundColor = Color.Yellow, - IsRegEx = false, - IsCaseSensitive = true, - IsLedSwitch = false, - IsSetBookmark = false, - IsActionEntry = false, - ActionEntry = null, - IsWordMatch = false - }; - - lock (_tempHighlightEntryListLock) - { - _tempHighlightEntryList.Add(he); - } + columnNamesLabel.Text = CalculateColumnNames(_filterParams); - dataGridView.CancelEdit(); - dataGridView.EndEdit(); - RefreshAllGrids(); - } + //CheckForFilterDirty(); //!!!GBro: Indicate to redo the search if search columns were changed + filterSearchButton.Image = _searchButtonImage; + saveFilterButton.Enabled = false; } + } - private void OnHighlightSelectionInLogFilewordModeToolStripMenuItemClick (object sender, EventArgs e) - { - if (dataGridView.EditingControl is DataGridViewTextBoxEditingControl ctl) - { - HighlightEntry he = new() - { - SearchText = ctl.SelectedText, - ForegroundColor = Color.Red, - BackgroundColor = Color.Yellow, - IsRegEx = false, - IsCaseSensitive = true, - IsLedSwitch = false, - IsStopTail = false, - IsSetBookmark = false, - IsActionEntry = false, - ActionEntry = null, - IsWordMatch = true - }; - - lock (_tempHighlightEntryListLock) - { - _tempHighlightEntryList.Add(he); - } + #endregion - dataGridView.CancelEdit(); - dataGridView.EndEdit(); - RefreshAllGrids(); - } - } + #region Column Header Context Menu - private void OnEditModeCopyToolStripMenuItemClick (object sender, EventArgs e) + private void OnDataGridViewCellContextMenuStripNeeded (object sender, DataGridViewCellContextMenuStripNeededEventArgs e) + { + if (e.RowIndex >= 0 && e.RowIndex < dataGridView.RowCount && !dataGridView.Rows[e.RowIndex].Selected) { - if (dataGridView.EditingControl is DataGridViewTextBoxEditingControl ctl) - { - if (Util.IsNull(ctl.SelectedText) == false) - { - Clipboard.SetText(ctl.SelectedText); - } - } + SelectLine(e.RowIndex, false, true); + } + else if (e.RowIndex < 0) + { + e.ContextMenuStrip = columnContextMenuStrip; } - private void OnRemoveAllToolStripMenuItemClick (object sender, EventArgs e) + if (e.ContextMenuStrip == columnContextMenuStrip) { - RemoveTempHighlights(); + _selectedCol = e.ColumnIndex; } + } - private void OnMakePermanentToolStripMenuItemClick (object sender, EventArgs e) + //private void boomarkDataGridView_CellContextMenuStripNeeded(object sender, DataGridViewCellContextMenuStripNeededEventArgs e) + //{ + // if (e.RowIndex > 0 && e.RowIndex < this.boomarkDataGridView.RowCount + // && !this.boomarkDataGridView.Rows[e.RowIndex].Selected) + // { + // this.boomarkDataGridView.Rows[e.RowIndex].Selected = true; + // this.boomarkDataGridView.CurrentCell = this.boomarkDataGridView.Rows[e.RowIndex].Cells[0]; + // } + // if (e.ContextMenuStrip == this.columnContextMenuStrip) + // { + // this.selectedCol = e.ColumnIndex; + // } + //} + + private void OnFilterGridViewCellContextMenuStripNeeded (object sender, DataGridViewCellContextMenuStripNeededEventArgs e) + { + if (e.ContextMenuStrip == columnContextMenuStrip) { - lock (_tempHighlightEntryListLock) - { - lock (_currentHighlightGroupLock) - { - _currentHighlightGroup.HighlightEntryList.AddRange(_tempHighlightEntryList); - RemoveTempHighlights(); - OnCurrentHighlightListChanged(); - } - } + _selectedCol = e.ColumnIndex; } + } - private void OnMarkCurrentFilterRangeToolStripMenuItemClick (object sender, EventArgs e) + private void OnColumnContextMenuStripOpening (object sender, CancelEventArgs e) + { + Control ctl = columnContextMenuStrip.SourceControl; + var gridView = ctl as BufferedDataGridView; + var frozen = false; + if (_freezeStateMap.TryGetValue(ctl, out var value)) { - MarkCurrentFilterRange(); + frozen = value; } - private void OnFilterForSelectionToolStripMenuItemClick (object sender, EventArgs e) + freezeLeftColumnsUntilHereToolStripMenuItem.Checked = frozen; + + if (frozen) + { + freezeLeftColumnsUntilHereToolStripMenuItem.Text = "Frozen"; + } + else { - if (dataGridView.EditingControl is DataGridViewTextBoxEditingControl ctl) + if (ctl is BufferedDataGridView) { - splitContainerLogWindow.Panel2Collapsed = false; - ResetFilterControls(); - FilterSearch(ctl.SelectedText); + freezeLeftColumnsUntilHereToolStripMenuItem.Text = $"Freeze left columns until here ({gridView.Columns[_selectedCol].HeaderText})"; } } - private void OnSetSelectedTextAsBookmarkCommentToolStripMenuItemClick (object sender, EventArgs e) + + DataGridViewColumn col = gridView.Columns[_selectedCol]; + moveLeftToolStripMenuItem.Enabled = col != null && col.DisplayIndex > 0; + moveRightToolStripMenuItem.Enabled = col != null && col.DisplayIndex < gridView.Columns.Count - 1; + + if (gridView.Columns.Count - 1 > _selectedCol) { - if (dataGridView.EditingControl is DataGridViewTextBoxEditingControl ctl) - { - AddBookmarkComment(ctl.SelectedText); - } + // DataGridViewColumn colRight = gridView.Columns[this.selectedCol + 1]; + DataGridViewColumn colRight = gridView.Columns.GetNextColumn(col, DataGridViewElementStates.None, DataGridViewElementStates.None); + moveRightToolStripMenuItem.Enabled = colRight != null && colRight.Frozen == col.Frozen; } - private void OnDataGridViewCellClick (object sender, DataGridViewCellEventArgs e) + if (_selectedCol > 0) { - _shouldCallTimeSync = true; + //DataGridViewColumn colLeft = gridView.Columns[this.selectedCol - 1]; + DataGridViewColumn colLeft = gridView.Columns.GetPreviousColumn(col, DataGridViewElementStates.None, DataGridViewElementStates.None); + + moveLeftToolStripMenuItem.Enabled = colLeft != null && colLeft.Frozen == col.Frozen; } - private void OnDataGridViewCellDoubleClick (object sender, DataGridViewCellEventArgs e) + DataGridViewColumn colLast = gridView.Columns[gridView.Columns.Count - 1]; + moveToLastColumnToolStripMenuItem.Enabled = colLast != null && colLast.Frozen == col.Frozen; + + // Fill context menu with column names + // + EventHandler ev = OnHandleColumnItemContextMenu; + allColumnsToolStripMenuItem.DropDownItems.Clear(); + foreach (DataGridViewColumn column in gridView.Columns) { - if (e.ColumnIndex == 0) + if (column.HeaderText.Length > 0) { - ToggleBookmark(); + var item = allColumnsToolStripMenuItem.DropDownItems.Add(column.HeaderText, null, ev) as ToolStripMenuItem; + item.Tag = column; + item.Enabled = !column.Frozen; } } + } - private void OnDataGridViewOverlayDoubleClicked (object sender, OverlayEventArgs e) + private void OnHandleColumnItemContextMenu (object sender, EventArgs args) + { + if (sender is ToolStripItem item) { - BookmarkComment(e.BookmarkOverlay.Bookmark); + var column = item.Tag as DataGridViewColumn; + column.Visible = true; + column.DataGridView.FirstDisplayedScrollingColumnIndex = column.Index; } + } - private void OnFilterRegexCheckBoxMouseUp (object sender, MouseEventArgs e) - { - if (e.Button == MouseButtons.Right) - { - RegexHelperDialog dlg = new() - { - ExpressionHistoryList = ConfigManager.Settings.RegexHistory.ExpressionHistoryList, - TesttextHistoryList = ConfigManager.Settings.RegexHistory.TesttextHistoryList, - Owner = this, - CaseSensitive = filterCaseSensitiveCheckBox.Checked, - Pattern = filterComboBox.Text - }; - - if (dlg.ShowDialog() == DialogResult.OK) - { - ConfigManager.Settings.RegexHistory.ExpressionHistoryList = dlg.ExpressionHistoryList; - ConfigManager.Settings.RegexHistory.TesttextHistoryList = dlg.TesttextHistoryList; - - filterCaseSensitiveCheckBox.Checked = dlg.CaseSensitive; - filterComboBox.Text = dlg.Pattern; + private void OnFreezeLeftColumnsUntilHereToolStripMenuItemClick (object sender, EventArgs e) + { + Control ctl = columnContextMenuStrip.SourceControl; + var frozen = false; - ConfigManager.Save(SettingsFlags.RegexHistory); - } - } + if (_freezeStateMap.TryGetValue(ctl, out var value)) + { + frozen = value; } - #endregion - - #region Filter-Highlight + frozen = !frozen; + _freezeStateMap[ctl] = frozen; - private void OnToggleHighlightPanelButtonClick (object sender, EventArgs e) + if (ctl is BufferedDataGridView gridView) { - ToggleHighlightPanel(highlightSplitContainer.Panel2Collapsed); + ApplyFrozenState(gridView); } + } - private void OnSaveFilterButtonClick (object sender, EventArgs e) + private void OnMoveToLastColumnToolStripMenuItemClick (object sender, EventArgs e) + { + var gridView = columnContextMenuStrip.SourceControl as BufferedDataGridView; + DataGridViewColumn col = gridView.Columns[_selectedCol]; + if (col != null) { - FilterParams newParams = _filterParams.Clone(); - newParams.Color = Color.FromKnownColor(KnownColor.Black); - ConfigManager.Settings.filterList.Add(newParams); - OnFilterListChanged(this); + col.DisplayIndex = gridView.Columns.Count - 1; } + } - private void OnDeleteFilterButtonClick (object sender, EventArgs e) + private void OnMoveLeftToolStripMenuItemClick (object sender, EventArgs e) + { + var gridView = columnContextMenuStrip.SourceControl as BufferedDataGridView; + DataGridViewColumn col = gridView.Columns[_selectedCol]; + if (col != null && col.DisplayIndex > 0) { - var index = filterListBox.SelectedIndex; - if (index >= 0) - { - var filterParams = (FilterParams)filterListBox.Items[index]; - ConfigManager.Settings.filterList.Remove(filterParams); - OnFilterListChanged(this); - if (filterListBox.Items.Count > 0) - { - filterListBox.SelectedIndex = filterListBox.Items.Count - 1; - } - } + col.DisplayIndex -= 1; } + } - private void OnFilterUpButtonClick (object sender, EventArgs e) + private void OnMoveRightToolStripMenuItemClick (object sender, EventArgs e) + { + var gridView = columnContextMenuStrip.SourceControl as BufferedDataGridView; + DataGridViewColumn col = gridView.Columns[_selectedCol]; + if (col != null && col.DisplayIndex < gridView.Columns.Count - 1) { - var i = filterListBox.SelectedIndex; - if (i > 0) - { - var filterParams = (FilterParams)filterListBox.Items[i]; - ConfigManager.Settings.filterList.RemoveAt(i); - i--; - ConfigManager.Settings.filterList.Insert(i, filterParams); - OnFilterListChanged(this); - filterListBox.SelectedIndex = i; - } + col.DisplayIndex = col.DisplayIndex + 1; } + } + + private void OnHideColumnToolStripMenuItemClick (object sender, EventArgs e) + { + var gridView = columnContextMenuStrip.SourceControl as BufferedDataGridView; + DataGridViewColumn col = gridView.Columns[_selectedCol]; + col.Visible = false; + } - private void OnFilterDownButtonClick (object sender, EventArgs e) + private void OnRestoreColumnsToolStripMenuItemClick (object sender, EventArgs e) + { + var gridView = columnContextMenuStrip.SourceControl as BufferedDataGridView; + foreach (DataGridViewColumn col in gridView.Columns) { - var i = filterListBox.SelectedIndex; - if (i < 0) - { - return; - } + col.Visible = true; + } + } + + private void OnTimeSpreadingControlLineSelected (object sender, SelectLineEventArgs e) + { + SelectLine(e.Line, false, true); + } + + private void OnBookmarkCommentToolStripMenuItemClick (object sender, EventArgs e) + { + AddBookmarkAndEditComment(); + } + + private void OnHighlightSelectionInLogFileToolStripMenuItemClick (object sender, EventArgs e) + { + if (dataGridView.EditingControl is DataGridViewTextBoxEditingControl ctl) + { + var he = new HighlightEntry() + { + SearchText = ctl.SelectedText, + ForegroundColor = Color.Red, + BackgroundColor = Color.Yellow, + IsRegEx = false, + IsCaseSensitive = true, + IsLedSwitch = false, + IsSetBookmark = false, + IsActionEntry = false, + ActionEntry = null, + IsWordMatch = false + }; - if (i < filterListBox.Items.Count - 1) + lock (_tempHighlightEntryListLock) { - var filterParams = (FilterParams)filterListBox.Items[i]; - ConfigManager.Settings.filterList.RemoveAt(i); - i++; - ConfigManager.Settings.filterList.Insert(i, filterParams); - OnFilterListChanged(this); - filterListBox.SelectedIndex = i; + _tempHighlightEntryList.Add(he); } + + dataGridView.CancelEdit(); + dataGridView.EndEdit(); + RefreshAllGrids(); } + } - private void OnFilterListBoxMouseDoubleClick (object sender, MouseEventArgs e) - { - if (filterListBox.SelectedIndex >= 0) - { - var filterParams = (FilterParams)filterListBox.Items[filterListBox.SelectedIndex]; - FilterParams newParams = filterParams.Clone(); - //newParams.historyList = ConfigManager.Settings.filterHistoryList; - this._filterParams = newParams; - ReInitFilterParams(this._filterParams); - ApplyFilterParams(); - CheckForAdvancedButtonDirty(); - CheckForFilterDirty(); - filterSearchButton.Image = _searchButtonImage; - saveFilterButton.Enabled = false; - if (hideFilterListOnLoadCheckBox.Checked) - { - ToggleHighlightPanel(false); - } + private void OnHighlightSelectionInLogFilewordModeToolStripMenuItemClick (object sender, EventArgs e) + { + if (dataGridView.EditingControl is DataGridViewTextBoxEditingControl ctl) + { + HighlightEntry he = new() + { + SearchText = ctl.SelectedText, + ForegroundColor = Color.Red, + BackgroundColor = Color.Yellow, + IsRegEx = false, + IsCaseSensitive = true, + IsLedSwitch = false, + IsStopTail = false, + IsSetBookmark = false, + IsActionEntry = false, + ActionEntry = null, + IsWordMatch = true + }; - if (filterOnLoadCheckBox.Checked) - { - FilterSearch(); - } + lock (_tempHighlightEntryListLock) + { + _tempHighlightEntryList.Add(he); } + + dataGridView.CancelEdit(); + dataGridView.EndEdit(); + RefreshAllGrids(); } + } - private void OnFilterListBoxDrawItem (object sender, DrawItemEventArgs e) + private void OnEditModeCopyToolStripMenuItemClick (object sender, EventArgs e) + { + if (dataGridView.EditingControl is DataGridViewTextBoxEditingControl ctl) { - e.DrawBackground(); - if (e.Index >= 0) + if (Util.IsNull(ctl.SelectedText) == false) { - var filterParams = (FilterParams)filterListBox.Items[e.Index]; - Rectangle rectangle = new(0, e.Bounds.Top, e.Bounds.Width, e.Bounds.Height); - - Brush brush; - - if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) - { - brush = new SolidBrush(filterListBox.BackColor); - } - else - { - brush = new SolidBrush(filterParams.Color); - } - - e.Graphics.DrawString(filterParams.SearchText, e.Font, brush, - new PointF(rectangle.Left, rectangle.Top)); - e.DrawFocusRectangle(); - brush.Dispose(); + Clipboard.SetText(ctl.SelectedText); } } + } + + private void OnRemoveAllToolStripMenuItemClick (object sender, EventArgs e) + { + RemoveTempHighlights(); + } - // Color for filter list entry - private void OnColorToolStripMenuItemClick (object sender, EventArgs e) + private void OnMakePermanentToolStripMenuItemClick (object sender, EventArgs e) + { + lock (_tempHighlightEntryListLock) { - var i = filterListBox.SelectedIndex; - if (i < filterListBox.Items.Count && i >= 0) + lock (_currentHighlightGroupLock) { - var filterParams = (FilterParams)filterListBox.Items[i]; - ColorDialog dlg = new(); - dlg.CustomColors = new[] { filterParams.Color.ToArgb() }; - dlg.Color = filterParams.Color; - if (dlg.ShowDialog() == DialogResult.OK) - { - filterParams.Color = dlg.Color; - filterListBox.Refresh(); - } + _currentHighlightGroup.HighlightEntryList.AddRange(_tempHighlightEntryList); + RemoveTempHighlights(); + OnCurrentHighlightListChanged(); } } + } - private void OnFilterCaseSensitiveCheckBoxCheckedChanged (object sender, EventArgs e) - { - CheckForFilterDirty(); - } + private void OnMarkCurrentFilterRangeToolStripMenuItemClick (object sender, EventArgs e) + { + MarkCurrentFilterRange(); + } - private void OnFilterRegexCheckBoxCheckedChanged (object sender, EventArgs e) + private void OnFilterForSelectionToolStripMenuItemClick (object sender, EventArgs e) + { + if (dataGridView.EditingControl is DataGridViewTextBoxEditingControl ctl) { - fuzzyKnobControl.Enabled = !filterRegexCheckBox.Checked; - fuzzyLabel.Enabled = !filterRegexCheckBox.Checked; - CheckForFilterDirty(); + splitContainerLogWindow.Panel2Collapsed = false; + ResetFilterControls(); + FilterSearch(ctl.SelectedText); } + } - private void OnInvertFilterCheckBoxCheckedChanged (object sender, EventArgs e) + private void OnSetSelectedTextAsBookmarkCommentToolStripMenuItemClick (object sender, EventArgs e) + { + if (dataGridView.EditingControl is DataGridViewTextBoxEditingControl ctl) { - CheckForFilterDirty(); + AddBookmarkComment(ctl.SelectedText); } + } - private void OnFilterRangeComboBoxTextChanged (object sender, EventArgs e) - { - CheckForFilterDirty(); - } + private void OnDataGridViewCellClick (object sender, DataGridViewCellEventArgs e) + { + _shouldCallTimeSync = true; + } - private void OnFuzzyKnobControlValueChanged (object sender, EventArgs e) + private void OnDataGridViewCellDoubleClick (object sender, DataGridViewCellEventArgs e) + { + if (e.ColumnIndex == 0) { - CheckForFilterDirty(); + ToggleBookmark(); } + } - private void OnFilterComboBoxTextChanged (object sender, EventArgs e) - { - CheckForFilterDirty(); - } + private void OnDataGridViewOverlayDoubleClicked (object sender, OverlayEventArgs e) + { + BookmarkComment(e.BookmarkOverlay.Bookmark); + } - private void OnSetBookmarksOnSelectedLinesToolStripMenuItemClick (object sender, EventArgs e) + private void OnFilterRegexCheckBoxMouseUp (object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Right) { - SetBookmarksForSelectedFilterLines(); - } + RegexHelperDialog dlg = new() + { + ExpressionHistoryList = ConfigManager.Settings.RegexHistory.ExpressionHistoryList, + TesttextHistoryList = ConfigManager.Settings.RegexHistory.TesttextHistoryList, + Owner = this, + CaseSensitive = filterCaseSensitiveCheckBox.Checked, + Pattern = filterComboBox.Text + }; - private void OnParentHighlightSettingsChanged (object sender, EventArgs e) - { - var groupName = _guiStateArgs.HighlightGroupName; - SetCurrentHighlightGroup(groupName); - } + if (dlg.ShowDialog() == DialogResult.OK) + { + ConfigManager.Settings.RegexHistory.ExpressionHistoryList = dlg.ExpressionHistoryList; + ConfigManager.Settings.RegexHistory.TesttextHistoryList = dlg.TesttextHistoryList; - private void OnFilterOnLoadCheckBoxMouseClick (object sender, MouseEventArgs e) - { - HandleChangedFilterOnLoadSetting(); - } + filterCaseSensitiveCheckBox.Checked = dlg.CaseSensitive; + filterComboBox.Text = dlg.Pattern; - private void OnFilterOnLoadCheckBoxKeyPress (object sender, KeyPressEventArgs e) - { - HandleChangedFilterOnLoadSetting(); + ConfigManager.Save(SettingsFlags.RegexHistory); + } } + } - private void OnHideFilterListOnLoadCheckBoxMouseClick (object sender, MouseEventArgs e) - { - HandleChangedFilterOnLoadSetting(); - } + #endregion - private void OnFilterToTabToolStripMenuItemClick (object sender, EventArgs e) - { - FilterToTab(); - } + #region Filter-Highlight - private void OnTimeSyncListWindowRemoved (object sender, EventArgs e) + private void OnToggleHighlightPanelButtonClick (object sender, EventArgs e) + { + ToggleHighlightPanel(highlightSplitContainer.Panel2Collapsed); + } + + private void OnSaveFilterButtonClick (object sender, EventArgs e) + { + FilterParams newParams = _filterParams.Clone(); + newParams.Color = Color.FromKnownColor(KnownColor.Black); + ConfigManager.Settings.filterList.Add(newParams); + OnFilterListChanged(this); + } + + private void OnDeleteFilterButtonClick (object sender, EventArgs e) + { + var index = filterListBox.SelectedIndex; + if (index >= 0) { - var syncList = sender as TimeSyncList; - lock (_timeSyncListLock) + var filterParams = (FilterParams)filterListBox.Items[index]; + ConfigManager.Settings.filterList.Remove(filterParams); + OnFilterListChanged(this); + if (filterListBox.Items.Count > 0) { - if (syncList.Count == 0 || syncList.Count == 1 && syncList.Contains(this)) - { - if (syncList == TimeSyncList) - { - TimeSyncList = null; - OnSyncModeChanged(); - } - } + filterListBox.SelectedIndex = filterListBox.Items.Count - 1; } } + } - private void OnFreeThisWindowFromTimeSyncToolStripMenuItemClick (object sender, EventArgs e) + private void OnFilterUpButtonClick (object sender, EventArgs e) + { + var i = filterListBox.SelectedIndex; + if (i > 0) { - FreeFromTimeSync(); + var filterParams = (FilterParams)filterListBox.Items[i]; + ConfigManager.Settings.filterList.RemoveAt(i); + i--; + ConfigManager.Settings.filterList.Insert(i, filterParams); + OnFilterListChanged(this); + filterListBox.SelectedIndex = i; } + } - private void OnSplitContainerSplitterMoved (object sender, SplitterEventArgs e) + private void OnFilterDownButtonClick (object sender, EventArgs e) + { + var i = filterListBox.SelectedIndex; + if (i < 0) { - advancedFilterSplitContainer.SplitterDistance = FILTER_ADVANCED_SPLITTER_DISTANCE; + return; } - private void OnMarkFilterHitsInLogViewToolStripMenuItemClick (object sender, EventArgs e) + if (i < filterListBox.Items.Count - 1) { - SearchParams p = new(); - p.SearchText = _filterParams.SearchText; - p.IsRegex = _filterParams.IsRegex; - p.IsCaseSensitive = _filterParams.IsCaseSensitive; - AddSearchHitHighlightEntry(p); + var filterParams = (FilterParams)filterListBox.Items[i]; + ConfigManager.Settings.filterList.RemoveAt(i); + i++; + ConfigManager.Settings.filterList.Insert(i, filterParams); + OnFilterListChanged(this); + filterListBox.SelectedIndex = i; } + } - private void OnColumnComboBoxSelectionChangeCommitted (object sender, EventArgs e) - { - SelectColumn(); - } + private void OnFilterListBoxMouseDoubleClick (object sender, MouseEventArgs e) + { + if (filterListBox.SelectedIndex >= 0) + { + var filterParams = (FilterParams)filterListBox.Items[filterListBox.SelectedIndex]; + FilterParams newParams = filterParams.Clone(); + //newParams.historyList = ConfigManager.Settings.filterHistoryList; + _filterParams = newParams; + ReInitFilterParams(_filterParams); + ApplyFilterParams(); + CheckForAdvancedButtonDirty(); + CheckForFilterDirty(); + filterSearchButton.Image = _searchButtonImage; + saveFilterButton.Enabled = false; + if (hideFilterListOnLoadCheckBox.Checked) + { + ToggleHighlightPanel(false); + } - private void OnColumnComboBoxKeyDown (object sender, KeyEventArgs e) - { - if (e.KeyCode == Keys.Enter) + if (filterOnLoadCheckBox.Checked) { - SelectColumn(); - dataGridView.Focus(); + FilterSearch(); } } + } - private void OnColumnComboBoxPreviewKeyDown (object sender, PreviewKeyDownEventArgs e) + private void OnFilterListBoxDrawItem (object sender, DrawItemEventArgs e) + { + e.DrawBackground(); + if (e.Index >= 0) { - if (e.KeyCode == Keys.Down && e.Modifiers == Keys.Alt) + var filterParams = (FilterParams)filterListBox.Items[e.Index]; + Rectangle rectangle = new(0, e.Bounds.Top, e.Bounds.Width, e.Bounds.Height); + + Brush brush; + + if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) { - columnComboBox.DroppedDown = true; + brush = new SolidBrush(filterListBox.BackColor); } - - if (e.KeyCode == Keys.Enter) + else { - e.IsInputKey = true; + brush = new SolidBrush(filterParams.Color); } + + e.Graphics.DrawString(filterParams.SearchText, e.Font, brush, + new PointF(rectangle.Left, rectangle.Top)); + e.DrawFocusRectangle(); + brush.Dispose(); } + } - private void OnBookmarkProviderBookmarkRemoved (object sender, EventArgs e) + // Color for filter list entry + private void OnColorToolStripMenuItemClick (object sender, EventArgs e) + { + var i = filterListBox.SelectedIndex; + if (i < filterListBox.Items.Count && i >= 0) { - if (!_isLoading) + var filterParams = (FilterParams)filterListBox.Items[i]; + ColorDialog dlg = new(); + dlg.CustomColors = [filterParams.Color.ToArgb()]; + dlg.Color = filterParams.Color; + if (dlg.ShowDialog() == DialogResult.OK) { - dataGridView.Refresh(); - filterGridView.Refresh(); + filterParams.Color = dlg.Color; + filterListBox.Refresh(); } } + } + + private void OnFilterCaseSensitiveCheckBoxCheckedChanged (object sender, EventArgs e) + { + CheckForFilterDirty(); + } + + private void OnFilterRegexCheckBoxCheckedChanged (object sender, EventArgs e) + { + fuzzyKnobControl.Enabled = !filterRegexCheckBox.Checked; + fuzzyLabel.Enabled = !filterRegexCheckBox.Checked; + CheckForFilterDirty(); + } + + private void OnInvertFilterCheckBoxCheckedChanged (object sender, EventArgs e) + { + CheckForFilterDirty(); + } + + private void OnFilterRangeComboBoxTextChanged (object sender, EventArgs e) + { + CheckForFilterDirty(); + } + + private void OnFuzzyKnobControlValueChanged (object sender, EventArgs e) + { + CheckForFilterDirty(); + } + + private void OnFilterComboBoxTextChanged (object sender, EventArgs e) + { + CheckForFilterDirty(); + } + + private void OnSetBookmarksOnSelectedLinesToolStripMenuItemClick (object sender, EventArgs e) + { + SetBookmarksForSelectedFilterLines(); + } + + private void OnParentHighlightSettingsChanged (object sender, EventArgs e) + { + var groupName = _guiStateArgs.HighlightGroupName; + SetCurrentHighlightGroup(groupName); + } + + private void OnFilterOnLoadCheckBoxMouseClick (object sender, MouseEventArgs e) + { + HandleChangedFilterOnLoadSetting(); + } + + private void OnFilterOnLoadCheckBoxKeyPress (object sender, KeyPressEventArgs e) + { + HandleChangedFilterOnLoadSetting(); + } + + private void OnHideFilterListOnLoadCheckBoxMouseClick (object sender, MouseEventArgs e) + { + HandleChangedFilterOnLoadSetting(); + } - private void OnBookmarkProviderBookmarkAdded (object sender, EventArgs e) + private void OnFilterToTabToolStripMenuItemClick (object sender, EventArgs e) + { + FilterToTab(); + } + + private void OnTimeSyncListWindowRemoved (object sender, EventArgs e) + { + var syncList = sender as TimeSyncList; + lock (_timeSyncListLock) { - if (!_isLoading) + if (syncList.Count == 0 || syncList.Count == 1 && syncList.Contains(this)) { - dataGridView.Refresh(); - filterGridView.Refresh(); + if (syncList == TimeSyncList) + { + TimeSyncList = null; + OnSyncModeChanged(); + } } } + } + + private void OnFreeThisWindowFromTimeSyncToolStripMenuItemClick (object sender, EventArgs e) + { + FreeFromTimeSync(); + } + + private void OnSplitContainerSplitterMoved (object sender, SplitterEventArgs e) + { + advancedFilterSplitContainer.SplitterDistance = FILTER_ADVANCED_SPLITTER_DISTANCE; + } + + private void OnMarkFilterHitsInLogViewToolStripMenuItemClick (object sender, EventArgs e) + { + SearchParams p = new(); + p.SearchText = _filterParams.SearchText; + p.IsRegex = _filterParams.IsRegex; + p.IsCaseSensitive = _filterParams.IsCaseSensitive; + AddSearchHitHighlightEntry(p); + } + + private void OnColumnComboBoxSelectionChangeCommitted (object sender, EventArgs e) + { + SelectColumn(); + } + + private void OnColumnComboBoxKeyDown (object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Enter) + { + SelectColumn(); + dataGridView.Focus(); + } + } - private void OnBookmarkProviderAllBookmarksRemoved (object sender, EventArgs e) + private void OnColumnComboBoxPreviewKeyDown (object sender, PreviewKeyDownEventArgs e) + { + if (e.KeyCode == Keys.Down && e.Modifiers == Keys.Alt) { - // nothing + columnComboBox.DroppedDown = true; } - private void OnLogWindowLeave (object sender, EventArgs e) + if (e.KeyCode == Keys.Enter) { - InvalidateCurrentRow(); + e.IsInputKey = true; } + } - private void OnLogWindowEnter (object sender, EventArgs e) + private void OnBookmarkProviderBookmarkRemoved (object sender, EventArgs e) + { + if (!_isLoading) { - InvalidateCurrentRow(); + dataGridView.Refresh(); + filterGridView.Refresh(); } + } - private void OnDataGridViewRowUnshared (object sender, DataGridViewRowEventArgs e) + private void OnBookmarkProviderBookmarkAdded (object sender, EventArgs e) + { + if (!_isLoading) { - if (_logger.IsTraceEnabled) - { - _logger.Trace($"Row unshared line {e.Row.Cells[1].Value}"); - } + dataGridView.Refresh(); + filterGridView.Refresh(); } + } - #endregion + private void OnBookmarkProviderAllBookmarksRemoved (object sender, EventArgs e) + { + // nothing + } - #endregion + private void OnLogWindowLeave (object sender, EventArgs e) + { + InvalidateCurrentRow(); + } - #endregion + private void OnLogWindowEnter (object sender, EventArgs e) + { + InvalidateCurrentRow(); + } - private void MeasureItem (object sender, MeasureItemEventArgs e) + private void OnDataGridViewRowUnshared (object sender, DataGridViewRowEventArgs e) + { + if (_logger.IsTraceEnabled) { - e.ItemHeight = filterListBox.Font.Height; + _logger.Trace($"Row unshared line {e.Row.Cells[1].Value}"); } } + + #endregion + + #endregion + + #endregion + + private void MeasureItem (object sender, MeasureItemEventArgs e) + { + e.ItemHeight = filterListBox.Font.Height; + } } diff --git a/src/LogExpert.UI/Controls/LogWindow/LogWindowPrivate.cs b/src/LogExpert.UI/Controls/LogWindow/LogWindowPrivate.cs index b26368fa..5ea20a31 100644 --- a/src/LogExpert.UI/Controls/LogWindow/LogWindowPrivate.cs +++ b/src/LogExpert.UI/Controls/LogWindow/LogWindowPrivate.cs @@ -16,793 +16,842 @@ using LogExpert.Extensions; using LogExpert.UI.Entities; -namespace LogExpert.UI.Controls.LogWindow +namespace LogExpert.UI.Controls.LogWindow; + +partial class LogWindow { - partial class LogWindow + #region Private Methods + + private void RegisterLogFileReaderEvents () { - #region Private Methods + _logFileReader.LoadFile += OnLogFileReaderLoadFile; + _logFileReader.LoadingFinished += OnLogFileReaderFinishedLoading; + _logFileReader.LoadingStarted += OnLogFileReaderLoadingStarted; + _logFileReader.FileNotFound += OnLogFileReaderFileNotFound; + _logFileReader.Respawned += OnLogFileReaderRespawned; + // FileSizeChanged is not registered here because it's registered after loading has finished + } - private void RegisterLogFileReaderEvents () + private void UnRegisterLogFileReaderEvents () + { + if (_logFileReader != null) { - _logFileReader.LoadFile += OnLogFileReaderLoadFile; - _logFileReader.LoadingFinished += OnLogFileReaderFinishedLoading; - _logFileReader.LoadingStarted += OnLogFileReaderLoadingStarted; - _logFileReader.FileNotFound += OnLogFileReaderFileNotFound; - _logFileReader.Respawned += OnLogFileReaderRespawned; - // FileSizeChanged is not registered here because it's registered after loading has finished + _logFileReader.LoadFile -= OnLogFileReaderLoadFile; + _logFileReader.LoadingFinished -= OnLogFileReaderFinishedLoading; + _logFileReader.LoadingStarted -= OnLogFileReaderLoadingStarted; + _logFileReader.FileNotFound -= OnLogFileReaderFileNotFound; + _logFileReader.Respawned -= OnLogFileReaderRespawned; + _logFileReader.FileSizeChanged -= OnFileSizeChanged; } + } + + private void CreateDefaultViewStyle () + { + DataGridViewCellStyle dataGridViewCellStyleMainGrid = new(); + DataGridViewCellStyle dataGridViewCellStyleFilterGrid = new(); + + dataGridViewCellStyleMainGrid.Alignment = DataGridViewContentAlignment.MiddleLeft; + dataGridViewCellStyleMainGrid.BackColor = SystemColors.Window; + dataGridViewCellStyleMainGrid.Font = new Font("Courier New", 8.25F, FontStyle.Regular, GraphicsUnit.Point, 0); + dataGridViewCellStyleMainGrid.ForeColor = SystemColors.ControlText; + dataGridViewCellStyleMainGrid.SelectionBackColor = SystemColors.Highlight; + dataGridViewCellStyleMainGrid.SelectionForeColor = SystemColors.HighlightText; + dataGridViewCellStyleMainGrid.WrapMode = DataGridViewTriState.False; + dataGridView.DefaultCellStyle = dataGridViewCellStyleMainGrid; + + dataGridViewCellStyleFilterGrid.Alignment = DataGridViewContentAlignment.MiddleLeft; + dataGridViewCellStyleFilterGrid.BackColor = SystemColors.Window; + dataGridViewCellStyleFilterGrid.Font = new Font("Courier New", 8.25F, FontStyle.Regular, GraphicsUnit.Point, 0); + dataGridViewCellStyleFilterGrid.ForeColor = SystemColors.ControlText; + dataGridViewCellStyleFilterGrid.SelectionBackColor = SystemColors.Highlight; + dataGridViewCellStyleFilterGrid.SelectionForeColor = SystemColors.HighlightText; + dataGridViewCellStyleFilterGrid.WrapMode = DataGridViewTriState.False; + filterGridView.DefaultCellStyle = dataGridViewCellStyleFilterGrid; + } - private void UnRegisterLogFileReaderEvents () + private bool LoadPersistenceOptions () + { + if (InvokeRequired) { - if (_logFileReader != null) - { - _logFileReader.LoadFile -= OnLogFileReaderLoadFile; - _logFileReader.LoadingFinished -= OnLogFileReaderFinishedLoading; - _logFileReader.LoadingStarted -= OnLogFileReaderLoadingStarted; - _logFileReader.FileNotFound -= OnLogFileReaderFileNotFound; - _logFileReader.Respawned -= OnLogFileReaderRespawned; - _logFileReader.FileSizeChanged -= OnFileSizeChanged; - } + return (bool)Invoke(new BoolReturnDelegate(LoadPersistenceOptions)); } - private void CreateDefaultViewStyle () + if (!Preferences.saveSessions && ForcedPersistenceFileName == null) { - DataGridViewCellStyle dataGridViewCellStyleMainGrid = new(); - DataGridViewCellStyle dataGridViewCellStyleFilterGrid = new(); - - dataGridViewCellStyleMainGrid.Alignment = DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyleMainGrid.BackColor = SystemColors.Window; - dataGridViewCellStyleMainGrid.Font = new Font("Courier New", 8.25F, FontStyle.Regular, GraphicsUnit.Point, 0); - dataGridViewCellStyleMainGrid.ForeColor = SystemColors.ControlText; - dataGridViewCellStyleMainGrid.SelectionBackColor = SystemColors.Highlight; - dataGridViewCellStyleMainGrid.SelectionForeColor = SystemColors.HighlightText; - dataGridViewCellStyleMainGrid.WrapMode = DataGridViewTriState.False; - dataGridView.DefaultCellStyle = dataGridViewCellStyleMainGrid; - - dataGridViewCellStyleFilterGrid.Alignment = DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyleFilterGrid.BackColor = SystemColors.Window; - dataGridViewCellStyleFilterGrid.Font = new Font("Courier New", 8.25F, FontStyle.Regular, GraphicsUnit.Point, 0); - dataGridViewCellStyleFilterGrid.ForeColor = SystemColors.ControlText; - dataGridViewCellStyleFilterGrid.SelectionBackColor = SystemColors.Highlight; - dataGridViewCellStyleFilterGrid.SelectionForeColor = SystemColors.HighlightText; - dataGridViewCellStyleFilterGrid.WrapMode = DataGridViewTriState.False; - filterGridView.DefaultCellStyle = dataGridViewCellStyleFilterGrid; + return false; } - private bool LoadPersistenceOptions () + try { - if (InvokeRequired) + PersistenceData persistenceData; + if (ForcedPersistenceFileName == null) + { + persistenceData = Persister.LoadPersistenceDataOptionsOnly(FileName, Preferences); + } + else { - return (bool)Invoke(new BoolReturnDelegate(LoadPersistenceOptions)); + persistenceData = + Persister.LoadPersistenceDataOptionsOnlyFromFixedFile(ForcedPersistenceFileName); } - if (!Preferences.saveSessions && ForcedPersistenceFileName == null) + if (persistenceData == null) { + _logger.Info($"No persistence data for {FileName} found."); return false; } - try + IsMultiFile = persistenceData.multiFile; + _multiFileOptions = new MultiFileOptions(); + _multiFileOptions.FormatPattern = persistenceData.multiFilePattern; + _multiFileOptions.MaxDayTry = persistenceData.multiFileMaxDays; + + if (string.IsNullOrEmpty(_multiFileOptions.FormatPattern)) { - PersistenceData persistenceData; - if (ForcedPersistenceFileName == null) - { - persistenceData = Persister.LoadPersistenceDataOptionsOnly(FileName, Preferences); - } - else - { - persistenceData = - Persister.LoadPersistenceDataOptionsOnlyFromFixedFile(ForcedPersistenceFileName); - } + _multiFileOptions = ObjectClone.Clone(Preferences.multiFileOptions); + } - if (persistenceData == null) - { - _logger.Info($"No persistence data for {FileName} found."); - return false; - } + splitContainerLogWindow.SplitterDistance = persistenceData.filterPosition; + splitContainerLogWindow.Panel2Collapsed = !persistenceData.filterVisible; + ToggleHighlightPanel(persistenceData.filterSaveListVisible); + ShowAdvancedFilterPanel(persistenceData.filterAdvanced); - IsMultiFile = persistenceData.multiFile; - _multiFileOptions = new MultiFileOptions(); - _multiFileOptions.FormatPattern = persistenceData.multiFilePattern; - _multiFileOptions.MaxDayTry = persistenceData.multiFileMaxDays; + if (_reloadMemento == null) + { + PreselectColumnizer(persistenceData.columnizerName); + } - if (string.IsNullOrEmpty(_multiFileOptions.FormatPattern)) - { - _multiFileOptions = ObjectClone.Clone(Preferences.multiFileOptions); - } + FollowTailChanged(persistenceData.followTail, false); + if (persistenceData.tabName != null) + { + Text = persistenceData.tabName; + } - splitContainerLogWindow.SplitterDistance = persistenceData.filterPosition; - splitContainerLogWindow.Panel2Collapsed = !persistenceData.filterVisible; - ToggleHighlightPanel(persistenceData.filterSaveListVisible); - ShowAdvancedFilterPanel(persistenceData.filterAdvanced); + AdjustHighlightSplitterWidth(); + SetCurrentHighlightGroup(persistenceData.highlightGroupName); - if (_reloadMemento == null) - { - PreselectColumnizer(persistenceData.columnizerName); - } + if (persistenceData.multiFileNames.Count > 0) + { + _logger.Info("Detected MultiFile name list in persistence options"); + _fileNames = new string[persistenceData.multiFileNames.Count]; + persistenceData.multiFileNames.CopyTo(_fileNames); + } + else + { + _fileNames = null; + } - FollowTailChanged(persistenceData.followTail, false); - if (persistenceData.tabName != null) - { - Text = persistenceData.tabName; - } + //this.bookmarkWindow.ShowBookmarkCommentColumn = persistenceData.showBookmarkCommentColumn; + SetExplicitEncoding(persistenceData.encoding); + return true; + } + catch (Exception ex) + { + _logger.Error(ex, "Error loading persistence data: "); + return false; + } + } - AdjustHighlightSplitterWidth(); - SetCurrentHighlightGroup(persistenceData.highlightGroupName); + private void SetDefaultsFromPrefs () + { + filterTailCheckBox.Checked = Preferences.filterTail; + syncFilterCheckBox.Checked = Preferences.filterSync; + FollowTailChanged(Preferences.followTail, false); + _multiFileOptions = ObjectClone.Clone(Preferences.multiFileOptions); + } - if (persistenceData.multiFileNames.Count > 0) - { - _logger.Info("Detected MultiFile name list in persistence options"); - _fileNames = new string[persistenceData.multiFileNames.Count]; - persistenceData.multiFileNames.CopyTo(_fileNames); - } - else - { - _fileNames = null; - } + private void LoadPersistenceData () + { + if (InvokeRequired) + { + Invoke(new MethodInvoker(LoadPersistenceData)); + return; + } - //this.bookmarkWindow.ShowBookmarkCommentColumn = persistenceData.showBookmarkCommentColumn; - SetExplicitEncoding(persistenceData.encoding); - return true; - } - catch (Exception ex) - { - _logger.Error(ex, "Error loading persistence data: "); - return false; - } + if (!Preferences.saveSessions && !ForcePersistenceLoading && ForcedPersistenceFileName == null) + { + SetDefaultsFromPrefs(); + return; } - private void SetDefaultsFromPrefs () + if (IsTempFile) { - filterTailCheckBox.Checked = Preferences.filterTail; - syncFilterCheckBox.Checked = Preferences.filterSync; - FollowTailChanged(Preferences.followTail, false); - _multiFileOptions = ObjectClone.Clone(Preferences.multiFileOptions); + SetDefaultsFromPrefs(); + return; } - private void LoadPersistenceData () + ForcePersistenceLoading = false; // force only 1 time (while session load) + + try { - if (InvokeRequired) + PersistenceData persistenceData; + + if (ForcedPersistenceFileName == null) { - Invoke(new MethodInvoker(LoadPersistenceData)); - return; + persistenceData = Persister.LoadPersistenceData(FileName, Preferences); } - - if (!Preferences.saveSessions && !ForcePersistenceLoading && ForcedPersistenceFileName == null) + else { - SetDefaultsFromPrefs(); - return; + persistenceData = Persister.LoadPersistenceDataFromFixedFile(ForcedPersistenceFileName); } - if (IsTempFile) + if (persistenceData.lineCount > _logFileReader.LineCount) { - SetDefaultsFromPrefs(); + // outdated persistence data (logfile rollover) + // MessageBox.Show(this, "Persistence data for " + this.FileName + " is outdated. It was discarded.", "Log Expert"); + _logger.Info($"Persistence data for {FileName} is outdated. It was discarded."); + _ = LoadPersistenceOptions(); return; } - ForcePersistenceLoading = false; // force only 1 time (while session load) - + _bookmarkProvider.SetBookmarks(persistenceData.bookmarkList); + _rowHeightList = persistenceData.rowHeightList; try { - PersistenceData persistenceData; - - if (ForcedPersistenceFileName == null) + if (persistenceData.currentLine >= 0 && persistenceData.currentLine < dataGridView.RowCount) { - persistenceData = Persister.LoadPersistenceData(FileName, Preferences); + SelectLine(persistenceData.currentLine, false, true); } else { - persistenceData = Persister.LoadPersistenceDataFromFixedFile(ForcedPersistenceFileName); - } - - if (persistenceData.lineCount > _logFileReader.LineCount) - { - // outdated persistence data (logfile rollover) - // MessageBox.Show(this, "Persistence data for " + this.FileName + " is outdated. It was discarded.", "Log Expert"); - _logger.Info($"Persistence data for {FileName} is outdated. It was discarded."); - _ = LoadPersistenceOptions(); - return; - } - - _bookmarkProvider.SetBookmarks(persistenceData.bookmarkList); - _rowHeightList = persistenceData.rowHeightList; - try - { - if (persistenceData.currentLine >= 0 && persistenceData.currentLine < dataGridView.RowCount) - { - SelectLine(persistenceData.currentLine, false, true); - } - else - { - if (_logFileReader.LineCount > 0) - { - dataGridView.FirstDisplayedScrollingRowIndex = _logFileReader.LineCount - 1; - SelectLine(_logFileReader.LineCount - 1, false, true); - } - } - - if (persistenceData.firstDisplayedLine >= 0 && - persistenceData.firstDisplayedLine < dataGridView.RowCount) - { - dataGridView.FirstDisplayedScrollingRowIndex = persistenceData.firstDisplayedLine; - } - - if (persistenceData.followTail) + if (_logFileReader.LineCount > 0) { - FollowTailChanged(persistenceData.followTail, false); + dataGridView.FirstDisplayedScrollingRowIndex = _logFileReader.LineCount - 1; + SelectLine(_logFileReader.LineCount - 1, false, true); } } - catch (ArgumentOutOfRangeException) + + if (persistenceData.firstDisplayedLine >= 0 && + persistenceData.firstDisplayedLine < dataGridView.RowCount) { - // FirstDisplayedScrollingRowIndex calculates sometimes the wrong scrolling ranges??? + dataGridView.FirstDisplayedScrollingRowIndex = persistenceData.firstDisplayedLine; } - if (Preferences.saveFilters) + if (persistenceData.followTail) { - RestoreFilters(persistenceData); + FollowTailChanged(persistenceData.followTail, false); } } - catch (IOException ex) - { - SetDefaultsFromPrefs(); - _logger.Error(ex, "Error loading bookmarks: "); - } - } - - private void RestoreFilters (PersistenceData persistenceData) - { - if (persistenceData.filterParamsList.Count > 0) - { - _filterParams = persistenceData.filterParamsList[0]; - ReInitFilterParams(_filterParams); - } - - ApplyFilterParams(); // re-loaded filter settingss - BeginInvoke(new MethodInvoker(FilterSearch)); - try - { - splitContainerLogWindow.SplitterDistance = persistenceData.filterPosition; - splitContainerLogWindow.Panel2Collapsed = !persistenceData.filterVisible; - } - catch (InvalidOperationException e) + catch (ArgumentOutOfRangeException) { - _logger.Error(e, "Error setting splitter distance: "); + // FirstDisplayedScrollingRowIndex calculates sometimes the wrong scrolling ranges??? } - ShowAdvancedFilterPanel(persistenceData.filterAdvanced); - if (_filterPipeList.Count == 0) // don't restore if it's only a reload + if (Preferences.saveFilters) { - RestoreFilterTabs(persistenceData); + RestoreFilters(persistenceData); } } - - private void RestoreFilterTabs (PersistenceData persistenceData) + catch (IOException ex) { - foreach (FilterTabData data in persistenceData.filterTabDataList) - { - FilterParams persistFilterParams = data.FilterParams; - ReInitFilterParams(persistFilterParams); - List filterResultList = []; - //List lastFilterResultList = new List(); - List filterHitList = []; - Filter(persistFilterParams, filterResultList, _lastFilterLinesList, filterHitList); - FilterPipe pipe = new(persistFilterParams.Clone(), this); - WritePipeToTab(pipe, filterResultList, data.PersistenceData.tabName, data.PersistenceData); - } + SetDefaultsFromPrefs(); + _logger.Error(ex, "Error loading bookmarks: "); } + } - private void ReInitFilterParams (FilterParams filterParams) + private void RestoreFilters (PersistenceData persistenceData) + { + if (persistenceData.filterParamsList.Count > 0) { - filterParams.SearchText = filterParams.SearchText; // init "lowerSearchText" - filterParams.RangeSearchText = filterParams.RangeSearchText; // init "lowerRangesearchText" - filterParams.CurrentColumnizer = CurrentColumnizer; - if (filterParams.IsRegex) - { - try - { - filterParams.CreateRegex(); - } - catch (ArgumentException) - { - StatusLineError("Invalid regular expression"); - } - } + _filterParams = persistenceData.filterParamsList[0]; + ReInitFilterParams(_filterParams); } - private void EnterLoadFileStatus () + ApplyFilterParams(); // re-loaded filter settingss + BeginInvoke(new MethodInvoker(FilterSearch)); + try { - _logger.Debug("EnterLoadFileStatus begin"); - - if (InvokeRequired) - { - Invoke(new MethodInvoker(EnterLoadFileStatus)); - return; - } - - _statusEventArgs.StatusText = "Loading file..."; - _statusEventArgs.LineCount = 0; - _statusEventArgs.FileSize = 0; - SendStatusLineUpdate(); + splitContainerLogWindow.SplitterDistance = persistenceData.filterPosition; + splitContainerLogWindow.Panel2Collapsed = !persistenceData.filterVisible; + } + catch (InvalidOperationException e) + { + _logger.Error(e, "Error setting splitter distance: "); + } - _progressEventArgs.MinValue = 0; - _progressEventArgs.MaxValue = 0; - _progressEventArgs.Value = 0; - _progressEventArgs.Visible = true; - SendProgressBarUpdate(); + ShowAdvancedFilterPanel(persistenceData.filterAdvanced); + if (_filterPipeList.Count == 0) // don't restore if it's only a reload + { + RestoreFilterTabs(persistenceData); + } + } - _isLoading = true; - _shouldCancel = true; - ClearFilterList(); - ClearBookmarkList(); - dataGridView.ClearSelection(); - dataGridView.RowCount = 0; - _logger.Debug("EnterLoadFileStatus end"); + private void RestoreFilterTabs (PersistenceData persistenceData) + { + foreach (FilterTabData data in persistenceData.filterTabDataList) + { + FilterParams persistFilterParams = data.FilterParams; + ReInitFilterParams(persistFilterParams); + List filterResultList = []; + //List lastFilterResultList = new List(); + List filterHitList = []; + Filter(persistFilterParams, filterResultList, _lastFilterLinesList, filterHitList); + FilterPipe pipe = new(persistFilterParams.Clone(), this); + WritePipeToTab(pipe, filterResultList, data.PersistenceData.tabName, data.PersistenceData); } + } - private void PositionAfterReload (ReloadMemento reloadMemento) + private void ReInitFilterParams (FilterParams filterParams) + { + filterParams.SearchText = filterParams.SearchText; // init "lowerSearchText" + filterParams.RangeSearchText = filterParams.RangeSearchText; // init "lowerRangesearchText" + filterParams.CurrentColumnizer = CurrentColumnizer; + if (filterParams.IsRegex) { - if (_reloadMemento.CurrentLine < dataGridView.RowCount && _reloadMemento.CurrentLine >= 0) + try { - dataGridView.CurrentCell = dataGridView.Rows[_reloadMemento.CurrentLine].Cells[0]; + filterParams.CreateRegex(); } - - if (_reloadMemento.FirstDisplayedLine < dataGridView.RowCount && _reloadMemento.FirstDisplayedLine >= 0) + catch (ArgumentException) { - dataGridView.FirstDisplayedScrollingRowIndex = _reloadMemento.FirstDisplayedLine; + StatusLineError("Invalid regular expression"); } } + } + + private void EnterLoadFileStatus () + { + _logger.Debug("EnterLoadFileStatus begin"); - private void LogfileDead () + if (InvokeRequired) { - _logger.Info("File not found."); - _isDeadFile = true; + Invoke(new MethodInvoker(EnterLoadFileStatus)); + return; + } - //this.logFileReader.FileSizeChanged -= this.FileSizeChangedHandler; - //if (this.logFileReader != null) - // this.logFileReader.stopMonitoring(); + _statusEventArgs.StatusText = "Loading file..."; + _statusEventArgs.LineCount = 0; + _statusEventArgs.FileSize = 0; + SendStatusLineUpdate(); - dataGridView.Enabled = false; - dataGridView.RowCount = 0; - _progressEventArgs.Visible = false; - _progressEventArgs.Value = _progressEventArgs.MaxValue; - SendProgressBarUpdate(); - _statusEventArgs.FileSize = 0; - _statusEventArgs.LineCount = 0; - _statusEventArgs.CurrentLineNum = 0; - SendStatusLineUpdate(); - _shouldCancel = true; - ClearFilterList(); - ClearBookmarkList(); + _progressEventArgs.MinValue = 0; + _progressEventArgs.MaxValue = 0; + _progressEventArgs.Value = 0; + _progressEventArgs.Visible = true; + SendProgressBarUpdate(); + + _isLoading = true; + _shouldCancel = true; + ClearFilterList(); + ClearBookmarkList(); + dataGridView.ClearSelection(); + dataGridView.RowCount = 0; + _logger.Debug("EnterLoadFileStatus end"); + } - StatusLineText("File not found"); - OnFileNotFound(EventArgs.Empty); + private void PositionAfterReload (ReloadMemento reloadMemento) + { + if (_reloadMemento.CurrentLine < dataGridView.RowCount && _reloadMemento.CurrentLine >= 0) + { + dataGridView.CurrentCell = dataGridView.Rows[_reloadMemento.CurrentLine].Cells[0]; } - private void LogfileRespawned () + if (_reloadMemento.FirstDisplayedLine < dataGridView.RowCount && _reloadMemento.FirstDisplayedLine >= 0) { - _logger.Info("LogfileDead(): Reloading file because it has been respawned."); - _isDeadFile = false; - dataGridView.Enabled = true; - StatusLineText(""); - OnFileRespawned(EventArgs.Empty); - Reload(); + dataGridView.FirstDisplayedScrollingRowIndex = _reloadMemento.FirstDisplayedLine; } + } + + private void LogfileDead () + { + _logger.Info("File not found."); + _isDeadFile = true; + + //this.logFileReader.FileSizeChanged -= this.FileSizeChangedHandler; + //if (this.logFileReader != null) + // this.logFileReader.stopMonitoring(); + + dataGridView.Enabled = false; + dataGridView.RowCount = 0; + _progressEventArgs.Visible = false; + _progressEventArgs.Value = _progressEventArgs.MaxValue; + SendProgressBarUpdate(); + _statusEventArgs.FileSize = 0; + _statusEventArgs.LineCount = 0; + _statusEventArgs.CurrentLineNum = 0; + SendStatusLineUpdate(); + _shouldCancel = true; + ClearFilterList(); + ClearBookmarkList(); + + StatusLineText("File not found"); + OnFileNotFound(EventArgs.Empty); + } + + private void LogfileRespawned () + { + _logger.Info("LogfileDead(): Reloading file because it has been respawned."); + _isDeadFile = false; + dataGridView.Enabled = true; + StatusLineText(""); + OnFileRespawned(EventArgs.Empty); + Reload(); + } - private void SetGuiAfterLoading () + private void SetGuiAfterLoading () + { + if (Text.Length == 0) { - if (Text.Length == 0) + if (IsTempFile) { - if (IsTempFile) - { - Text = TempTitleName; - } - else - { - Text = Util.GetNameFromPath(FileName); - } + Text = TempTitleName; + } + else + { + Text = Util.GetNameFromPath(FileName); } + } - ShowBookmarkBubbles = Preferences.showBubbles; - //if (this.forcedColumnizer == null) + ShowBookmarkBubbles = Preferences.showBubbles; + //if (this.forcedColumnizer == null) + { + ILogLineColumnizer columnizer; + if (_forcedColumnizerForLoading != null) { - ILogLineColumnizer columnizer; - if (_forcedColumnizerForLoading != null) - { - columnizer = _forcedColumnizerForLoading; - _forcedColumnizerForLoading = null; - } - else + columnizer = _forcedColumnizerForLoading; + _forcedColumnizerForLoading = null; + } + else + { + columnizer = FindColumnizer(); + if (columnizer != null) { - columnizer = FindColumnizer(); - if (columnizer != null) - { - if (_reloadMemento == null) - { - //TODO this needs to be refactored - var directory = ConfigManager.Settings.Preferences.PortableMode ? ConfigManager.PortableModeDir : ConfigManager.ConfigDir; - - columnizer = ColumnizerPicker.CloneColumnizer(columnizer, directory); - } - } - else + if (_reloadMemento == null) { //TODO this needs to be refactored var directory = ConfigManager.Settings.Preferences.PortableMode ? ConfigManager.PortableModeDir : ConfigManager.ConfigDir; - // Default Columnizers - columnizer = ColumnizerPicker.CloneColumnizer(ColumnizerPicker.FindColumnizer(FileName, _logFileReader, PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers), directory); + columnizer = ColumnizerPicker.CloneColumnizer(columnizer, directory); } } - - Invoke(new SetColumnizerFx(SetColumnizer), columnizer); - } - dataGridView.Enabled = true; - DisplayCurrentFileOnStatusline(); - //this.guiStateArgs.FollowTail = this.Preferences.followTail; - _guiStateArgs.MultiFileEnabled = !IsTempFile; - _guiStateArgs.MenuEnabled = true; - _guiStateArgs.CurrentEncoding = _logFileReader.CurrentEncoding; - SendGuiStateUpdate(); - //if (this.dataGridView.RowCount > 0) - // SelectLine(this.dataGridView.RowCount - 1); - //if (this.dataGridView.Columns.Count > 1) - //{ - // this.dataGridView.Columns[this.dataGridView.Columns.Count-1].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells; - // this.dataGridView.Columns[this.dataGridView.Columns.Count - 1].AutoSizeMode = DataGridViewAutoSizeColumnMode.NotSet; - // AdjustMinimumGridWith(); - //} - if (CurrentColumnizer.IsTimeshiftImplemented()) - { - if (Preferences.timestampControl) + else { - SetTimestampLimits(); - SyncTimestampDisplay(); - } + //TODO this needs to be refactored + var directory = ConfigManager.Settings.Preferences.PortableMode ? ConfigManager.PortableModeDir : ConfigManager.ConfigDir; - Settings settings = ConfigManager.Settings; - ShowLineColumn(!settings.hideLineColumn); + // Default Columnizers + columnizer = ColumnizerPicker.CloneColumnizer(ColumnizerPicker.FindColumnizer(FileName, _logFileReader, PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers), directory); + } } - ShowTimeSpread(Preferences.showTimeSpread && CurrentColumnizer.IsTimeshiftImplemented()); - locateLineInOriginalFileToolStripMenuItem.Enabled = FilterPipe != null; + Invoke(new SetColumnizerFx(SetColumnizer), columnizer); } - - private ILogLineColumnizer FindColumnizer () + dataGridView.Enabled = true; + DisplayCurrentFileOnStatusline(); + //this.guiStateArgs.FollowTail = this.Preferences.followTail; + _guiStateArgs.MultiFileEnabled = !IsTempFile; + _guiStateArgs.MenuEnabled = true; + _guiStateArgs.CurrentEncoding = _logFileReader.CurrentEncoding; + SendGuiStateUpdate(); + //if (this.dataGridView.RowCount > 0) + // SelectLine(this.dataGridView.RowCount - 1); + //if (this.dataGridView.Columns.Count > 1) + //{ + // this.dataGridView.Columns[this.dataGridView.Columns.Count-1].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells; + // this.dataGridView.Columns[this.dataGridView.Columns.Count - 1].AutoSizeMode = DataGridViewAutoSizeColumnMode.NotSet; + // AdjustMinimumGridWith(); + //} + if (CurrentColumnizer.IsTimeshiftImplemented()) { - ILogLineColumnizer columnizer; - if (Preferences.maskPrio) - { - columnizer = _parentLogTabWin.FindColumnizerByFileMask(Util.GetNameFromPath(FileName)) ?? _parentLogTabWin.GetColumnizerHistoryEntry(FileName); - } - else + if (Preferences.timestampControl) { - columnizer = _parentLogTabWin.GetColumnizerHistoryEntry(FileName) ?? _parentLogTabWin.FindColumnizerByFileMask(Util.GetNameFromPath(FileName)); + SetTimestampLimits(); + SyncTimestampDisplay(); } - return columnizer; + Settings settings = ConfigManager.Settings; + ShowLineColumn(!settings.hideLineColumn); } - private void ReloadNewFile () - { - // prevent "overloads". May occur on very fast rollovers (next rollover before the file is reloaded) - lock (_reloadLock) - { - _reloadOverloadCounter++; - _logger.Info("ReloadNewFile(): counter = {0}", _reloadOverloadCounter); - if (_reloadOverloadCounter <= 1) - { - SavePersistenceData(false); - _loadingFinishedEvent.Reset(); - _externaLoadingFinishedEvent.Reset(); - Thread reloadFinishedThread = new(ReloadFinishedThreadFx); - reloadFinishedThread.IsBackground = true; - reloadFinishedThread.Start(); - LoadFile(FileName, EncodingOptions); - - ClearBookmarkList(); - SavePersistenceData(false); - - //if (this.filterTailCheckBox.Checked) - //{ - // _logger.logDebug("Waiting for loading to be complete."); - // loadingFinishedEvent.WaitOne(); - // _logger.logDebug("Refreshing filter view because of reload."); - // FilterSearch(); - //} - //LoadFilterPipes(); - } - else - { - _logger.Debug("Preventing reload because of recursive calls."); - } + ShowTimeSpread(Preferences.showTimeSpread && CurrentColumnizer.IsTimeshiftImplemented()); + locateLineInOriginalFileToolStripMenuItem.Enabled = FilterPipe != null; + } - _reloadOverloadCounter--; - } + private ILogLineColumnizer FindColumnizer () + { + ILogLineColumnizer columnizer; + if (Preferences.maskPrio) + { + columnizer = _parentLogTabWin.FindColumnizerByFileMask(Util.GetNameFromPath(FileName)) ?? _parentLogTabWin.GetColumnizerHistoryEntry(FileName); } - - private void ReloadFinishedThreadFx () + else { - _logger.Info("Waiting for loading to be complete."); - _loadingFinishedEvent.WaitOne(); - _logger.Info("Refreshing filter view because of reload."); - Invoke(new MethodInvoker(FilterSearch)); - LoadFilterPipes(); + columnizer = _parentLogTabWin.GetColumnizerHistoryEntry(FileName) ?? _parentLogTabWin.FindColumnizerByFileMask(Util.GetNameFromPath(FileName)); } - private void UpdateProgress (LoadFileEventArgs e) + return columnizer; + } + + private void ReloadNewFile () + { + // prevent "overloads". May occur on very fast rollovers (next rollover before the file is reloaded) + lock (_reloadLock) { - try + _reloadOverloadCounter++; + _logger.Info("ReloadNewFile(): counter = {0}", _reloadOverloadCounter); + if (_reloadOverloadCounter <= 1) { - if (e.ReadPos >= e.FileSize) - { - //_logger.Warn("UpdateProgress(): ReadPos (" + e.ReadPos + ") is greater than file size (" + e.FileSize + "). Aborting Update"); - return; - } + SavePersistenceData(false); + _loadingFinishedEvent.Reset(); + _externaLoadingFinishedEvent.Reset(); + Thread reloadFinishedThread = new(ReloadFinishedThreadFx); + reloadFinishedThread.IsBackground = true; + reloadFinishedThread.Start(); + LoadFile(FileName, EncodingOptions); + + ClearBookmarkList(); + SavePersistenceData(false); - _statusEventArgs.FileSize = e.ReadPos; - //this.progressEventArgs.Visible = true; - _progressEventArgs.MaxValue = (int)e.FileSize; - _progressEventArgs.Value = (int)e.ReadPos; - SendProgressBarUpdate(); - SendStatusLineUpdate(); + //if (this.filterTailCheckBox.Checked) + //{ + // _logger.logDebug("Waiting for loading to be complete."); + // loadingFinishedEvent.WaitOne(); + // _logger.logDebug("Refreshing filter view because of reload."); + // FilterSearch(); + //} + //LoadFilterPipes(); } - catch (Exception ex) + else { - _logger.Error(ex, "UpdateProgress(): "); + _logger.Debug("Preventing reload because of recursive calls."); } + + _reloadOverloadCounter--; } + } + + private void ReloadFinishedThreadFx () + { + _logger.Info("Waiting for loading to be complete."); + _loadingFinishedEvent.WaitOne(); + _logger.Info("Refreshing filter view because of reload."); + Invoke(new MethodInvoker(FilterSearch)); + LoadFilterPipes(); + } - private void LoadingStarted (LoadFileEventArgs e) + private void UpdateProgress (LoadFileEventArgs e) + { + try { - try + if (e.ReadPos >= e.FileSize) { - _statusEventArgs.FileSize = e.ReadPos; - _statusEventArgs.StatusText = "Loading " + Util.GetNameFromPath(e.FileName); - _progressEventArgs.Visible = true; - _progressEventArgs.MaxValue = (int)e.FileSize; - _progressEventArgs.Value = (int)e.ReadPos; - SendProgressBarUpdate(); - SendStatusLineUpdate(); - } - catch (Exception ex) - { - _logger.Error(ex, "LoadingStarted(): "); + //_logger.Warn("UpdateProgress(): ReadPos (" + e.ReadPos + ") is greater than file size (" + e.FileSize + "). Aborting Update"); + return; } - } - private void LoadingFinished () - { - _logger.Info("File loading complete."); - - StatusLineText(""); - _logFileReader.FileSizeChanged += OnFileSizeChanged; - _isLoading = false; - _shouldCancel = false; - dataGridView.SuspendLayout(); - dataGridView.RowCount = _logFileReader.LineCount; - dataGridView.CurrentCellChanged += OnDataGridViewCurrentCellChanged; - dataGridView.Enabled = true; - dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); - dataGridView.ResumeLayout(); - _progressEventArgs.Visible = false; - _progressEventArgs.Value = _progressEventArgs.MaxValue; + _statusEventArgs.FileSize = e.ReadPos; + //this.progressEventArgs.Visible = true; + _progressEventArgs.MaxValue = (int)e.FileSize; + _progressEventArgs.Value = (int)e.ReadPos; SendProgressBarUpdate(); - //if (this.logFileReader.LineCount > 0) - //{ - // this.dataGridView.FirstDisplayedScrollingRowIndex = this.logFileReader.LineCount - 1; - // SelectLine(this.logFileReader.LineCount - 1); - //} - _guiStateArgs.FollowTail = true; - SendGuiStateUpdate(); - _statusEventArgs.LineCount = _logFileReader.LineCount; - _statusEventArgs.FileSize = _logFileReader.FileSize; SendStatusLineUpdate(); - - PreferencesChanged(_parentLogTabWin.Preferences, true, SettingsFlags.All); - //LoadPersistenceData(); } + catch (Exception ex) + { + _logger.Error(ex, "UpdateProgress(): "); + } + } - private void LogEventWorker () + private void LoadingStarted (LoadFileEventArgs e) + { + try { - Thread.CurrentThread.Name = "LogEventWorker"; - while (true) - { - _logger.Debug("Waiting for signal"); - _logEventArgsEvent.WaitOne(); - _logger.Debug("Wakeup signal received."); - while (true) - { - LogEventArgs e; - var lastLineCount = 0; - lock (_logEventArgsList) - { - _logger.Info("{0} events in queue", _logEventArgsList.Count); - if (_logEventArgsList.Count == 0) - { - _logEventArgsEvent.Reset(); - break; - } + _statusEventArgs.FileSize = e.ReadPos; + _statusEventArgs.StatusText = "Loading " + Util.GetNameFromPath(e.FileName); + _progressEventArgs.Visible = true; + _progressEventArgs.MaxValue = (int)e.FileSize; + _progressEventArgs.Value = (int)e.ReadPos; + SendProgressBarUpdate(); + SendStatusLineUpdate(); + } + catch (Exception ex) + { + _logger.Error(ex, "LoadingStarted(): "); + } + } - e = _logEventArgsList[0]; - _logEventArgsList.RemoveAt(0); - } + private void LoadingFinished () + { + _logger.Info("File loading complete."); + + StatusLineText(""); + _logFileReader.FileSizeChanged += OnFileSizeChanged; + _isLoading = false; + _shouldCancel = false; + dataGridView.SuspendLayout(); + dataGridView.RowCount = _logFileReader.LineCount; + dataGridView.CurrentCellChanged += OnDataGridViewCurrentCellChanged; + dataGridView.Enabled = true; + dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); + dataGridView.ResumeLayout(); + _progressEventArgs.Visible = false; + _progressEventArgs.Value = _progressEventArgs.MaxValue; + SendProgressBarUpdate(); + //if (this.logFileReader.LineCount > 0) + //{ + // this.dataGridView.FirstDisplayedScrollingRowIndex = this.logFileReader.LineCount - 1; + // SelectLine(this.logFileReader.LineCount - 1); + //} + _guiStateArgs.FollowTail = true; + SendGuiStateUpdate(); + _statusEventArgs.LineCount = _logFileReader.LineCount; + _statusEventArgs.FileSize = _logFileReader.FileSize; + SendStatusLineUpdate(); + + PreferencesChanged(_parentLogTabWin.Preferences, true, SettingsFlags.All); + //LoadPersistenceData(); + } - if (e.IsRollover) + private void LogEventWorker () + { + Thread.CurrentThread.Name = "LogEventWorker"; + while (true) + { + _logger.Debug("Waiting for signal"); + _logEventArgsEvent.WaitOne(); + _logger.Debug("Wakeup signal received."); + while (true) + { + LogEventArgs e; + var lastLineCount = 0; + lock (_logEventArgsList) + { + _logger.Info("{0} events in queue", _logEventArgsList.Count); + if (_logEventArgsList.Count == 0) { - ShiftBookmarks(e.RolloverOffset); - ShiftRowHeightList(e.RolloverOffset); - ShiftFilterPipes(e.RolloverOffset); - lastLineCount = 0; + _logEventArgsEvent.Reset(); + break; } - else + + e = _logEventArgsList[0]; + _logEventArgsList.RemoveAt(0); + } + + if (e.IsRollover) + { + ShiftBookmarks(e.RolloverOffset); + ShiftRowHeightList(e.RolloverOffset); + ShiftFilterPipes(e.RolloverOffset); + lastLineCount = 0; + } + else + { + if (e.LineCount < lastLineCount) { - if (e.LineCount < lastLineCount) - { - _logger.Error("Line count of event is: {0}, should be greater than last line count: {1}", e.LineCount, lastLineCount); - } + _logger.Error("Line count of event is: {0}, should be greater than last line count: {1}", e.LineCount, lastLineCount); } - - Invoke(UpdateGrid, [e]); - CheckFilterAndHighlight(e); - _timeSpreadCalc.SetLineCount(e.LineCount); } + + Invoke(UpdateGrid, [e]); + CheckFilterAndHighlight(e); + _timeSpreadCalc.SetLineCount(e.LineCount); } } + } - private void StopLogEventWorkerThread () - { - _logEventArgsEvent.Set(); - cts.Cancel(); - //_logEventHandlerThread.Abort(); - //_logEventHandlerThread.Join(); - } + private void StopLogEventWorkerThread () + { + _logEventArgsEvent.Set(); + cts.Cancel(); + //_logEventHandlerThread.Abort(); + //_logEventHandlerThread.Join(); + } - private void OnFileSizeChanged (LogEventArgs e) + private void OnFileSizeChanged (LogEventArgs e) + { + FileSizeChanged?.Invoke(this, e); + } + + private void UpdateGrid (LogEventArgs e) + { + var oldRowCount = dataGridView.RowCount; + var firstDisplayedLine = dataGridView.FirstDisplayedScrollingRowIndex; + + if (dataGridView.CurrentCellAddress.Y >= e.LineCount) { - FileSizeChanged?.Invoke(this, e); + //this.dataGridView.Rows[this.dataGridView.CurrentCellAddress.Y].Selected = false; + //this.dataGridView.CurrentCell = this.dataGridView.Rows[0].Cells[0]; } - private void UpdateGrid (LogEventArgs e) + try { - var oldRowCount = dataGridView.RowCount; - var firstDisplayedLine = dataGridView.FirstDisplayedScrollingRowIndex; - - if (dataGridView.CurrentCellAddress.Y >= e.LineCount) - { - //this.dataGridView.Rows[this.dataGridView.CurrentCellAddress.Y].Selected = false; - //this.dataGridView.CurrentCell = this.dataGridView.Rows[0].Cells[0]; - } - - try + if (dataGridView.RowCount > e.LineCount) { - if (dataGridView.RowCount > e.LineCount) + var currentLineNum = dataGridView.CurrentCellAddress.Y; + dataGridView.RowCount = 0; + dataGridView.RowCount = e.LineCount; + if (_guiStateArgs.FollowTail == false) { - var currentLineNum = dataGridView.CurrentCellAddress.Y; - dataGridView.RowCount = 0; - dataGridView.RowCount = e.LineCount; - if (_guiStateArgs.FollowTail == false) + if (currentLineNum >= dataGridView.RowCount) { - if (currentLineNum >= dataGridView.RowCount) - { - currentLineNum = dataGridView.RowCount - 1; - } - - dataGridView.CurrentCell = dataGridView.Rows[currentLineNum].Cells[0]; + currentLineNum = dataGridView.RowCount - 1; } + + dataGridView.CurrentCell = dataGridView.Rows[currentLineNum].Cells[0]; } - else - { - dataGridView.RowCount = e.LineCount; - } + } + else + { + dataGridView.RowCount = e.LineCount; + } - _logger.Debug("UpdateGrid(): new RowCount={0}", dataGridView.RowCount); + _logger.Debug("UpdateGrid(): new RowCount={0}", dataGridView.RowCount); - if (e.IsRollover) + if (e.IsRollover) + { + // Multifile rollover + // keep selection and view range, if no follow tail mode + if (!_guiStateArgs.FollowTail) { - // Multifile rollover - // keep selection and view range, if no follow tail mode - if (!_guiStateArgs.FollowTail) + var currentLineNum = dataGridView.CurrentCellAddress.Y; + currentLineNum -= e.RolloverOffset; + if (currentLineNum < 0) { - var currentLineNum = dataGridView.CurrentCellAddress.Y; - currentLineNum -= e.RolloverOffset; - if (currentLineNum < 0) - { - currentLineNum = 0; - } - - _logger.Debug("UpdateGrid(): Rollover=true, Rollover offset={0}, currLineNum was {1}, new currLineNum={2}", e.RolloverOffset, dataGridView.CurrentCellAddress.Y, currentLineNum); - firstDisplayedLine -= e.RolloverOffset; - if (firstDisplayedLine < 0) - { - firstDisplayedLine = 0; - } - - dataGridView.FirstDisplayedScrollingRowIndex = firstDisplayedLine; - dataGridView.CurrentCell = dataGridView.Rows[currentLineNum].Cells[0]; - dataGridView.Rows[currentLineNum].Selected = true; + currentLineNum = 0; } - } - _statusEventArgs.LineCount = e.LineCount; - StatusLineFileSize(e.FileSize); - - if (!_isLoading) - { - if (oldRowCount == 0) + _logger.Debug("UpdateGrid(): Rollover=true, Rollover offset={0}, currLineNum was {1}, new currLineNum={2}", e.RolloverOffset, dataGridView.CurrentCellAddress.Y, currentLineNum); + firstDisplayedLine -= e.RolloverOffset; + if (firstDisplayedLine < 0) { - AdjustMinimumGridWith(); + firstDisplayedLine = 0; } - //CheckFilterAndHighlight(e); + dataGridView.FirstDisplayedScrollingRowIndex = firstDisplayedLine; + dataGridView.CurrentCell = dataGridView.Rows[currentLineNum].Cells[0]; + dataGridView.Rows[currentLineNum].Selected = true; } + } - if (_guiStateArgs.FollowTail && dataGridView.RowCount > 0) - { - dataGridView.FirstDisplayedScrollingRowIndex = dataGridView.RowCount - 1; - OnTailFollowed(EventArgs.Empty); - } + _statusEventArgs.LineCount = e.LineCount; + StatusLineFileSize(e.FileSize); - if (Preferences.timestampControl && !_isLoading) + if (!_isLoading) + { + if (oldRowCount == 0) { - SetTimestampLimits(); + AdjustMinimumGridWith(); } + + //CheckFilterAndHighlight(e); } - catch (Exception ex) + + if (_guiStateArgs.FollowTail && dataGridView.RowCount > 0) { - _logger.Error(ex, "Fehler bei UpdateGrid(): "); + dataGridView.FirstDisplayedScrollingRowIndex = dataGridView.RowCount - 1; + OnTailFollowed(EventArgs.Empty); } - //this.dataGridView.Refresh(); - //this.dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); + if (Preferences.timestampControl && !_isLoading) + { + SetTimestampLimits(); + } + } + catch (Exception ex) + { + _logger.Error(ex, "Fehler bei UpdateGrid(): "); } - private void CheckFilterAndHighlight (LogEventArgs e) + //this.dataGridView.Refresh(); + //this.dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); + } + + private void CheckFilterAndHighlight (LogEventArgs e) + { + var noLed = true; + bool suppressLed; + bool setBookmark; + bool stopTail; + string bookmarkComment; + + if (filterTailCheckBox.Checked || _filterPipeList.Count > 0) { - var noLed = true; - bool suppressLed; - bool setBookmark; - bool stopTail; - string bookmarkComment; + var filterStart = e.PrevLineCount; + if (e.IsRollover) + { + ShiftFilterLines(e.RolloverOffset); + filterStart -= e.RolloverOffset; + } - if (filterTailCheckBox.Checked || _filterPipeList.Count > 0) + var firstStopTail = true; + ColumnizerCallback callback = new(this); + var filterLineAdded = false; + for (var i = filterStart; i < e.LineCount; ++i) { - var filterStart = e.PrevLineCount; - if (e.IsRollover) + ILogLine line = _logFileReader.GetLogLine(i); + if (line == null) { - ShiftFilterLines(e.RolloverOffset); - filterStart -= e.RolloverOffset; + return; } - var firstStopTail = true; - ColumnizerCallback callback = new(this); - var filterLineAdded = false; - for (var i = filterStart; i < e.LineCount; ++i) + if (filterTailCheckBox.Checked) { - ILogLine line = _logFileReader.GetLogLine(i); - if (line == null) + callback.SetLineNum(i); + if (Util.TestFilterCondition(_filterParams, line, callback)) { - return; + //AddFilterLineFx addFx = new AddFilterLineFx(AddFilterLine); + //this.Invoke(addFx, new object[] { i, true }); + filterLineAdded = true; + AddFilterLine(i, false, _filterParams, _filterResultList, _lastFilterLinesList, + _filterHitList); } + } + + //ProcessFilterPipeFx pipeFx = new ProcessFilterPipeFx(ProcessFilterPipes); + //pipeFx.BeginInvoke(i, null, null); + ProcessFilterPipes(i); + + IList matchingList = FindMatchingHilightEntries(line); + LaunchHighlightPlugins(matchingList, i); + GetHilightActions(matchingList, out suppressLed, out stopTail, out setBookmark, out bookmarkComment); + if (setBookmark) + { + SetBookmarkFx fx = SetBookmarkFromTrigger; + fx.BeginInvoke(i, bookmarkComment, null, null); + } - if (filterTailCheckBox.Checked) + if (stopTail && _guiStateArgs.FollowTail) + { + var wasFollow = _guiStateArgs.FollowTail; + FollowTailChanged(false, true); + if (firstStopTail && wasFollow) { - callback.SetLineNum(i); - if (Util.TestFilterCondition(_filterParams, line, callback)) - { - //AddFilterLineFx addFx = new AddFilterLineFx(AddFilterLine); - //this.Invoke(addFx, new object[] { i, true }); - filterLineAdded = true; - AddFilterLine(i, false, _filterParams, _filterResultList, _lastFilterLinesList, - _filterHitList); - } + Invoke(new SelectLineFx(SelectAndEnsureVisible), [i, false]); + firstStopTail = false; } + } + + if (!suppressLed) + { + noLed = false; + } + } - //ProcessFilterPipeFx pipeFx = new ProcessFilterPipeFx(ProcessFilterPipes); - //pipeFx.BeginInvoke(i, null, null); - ProcessFilterPipes(i); + if (filterLineAdded) + { + //AddFilterLineGuiUpdateFx addFx = new AddFilterLineGuiUpdateFx(AddFilterLineGuiUpdate); + //this.Invoke(addFx); + TriggerFilterLineGuiUpdate(); + } + } + else + { + var firstStopTail = true; + var startLine = e.PrevLineCount; + if (e.IsRollover) + { + ShiftFilterLines(e.RolloverOffset); + startLine -= e.RolloverOffset; + } + for (var i = startLine; i < e.LineCount; ++i) + { + ILogLine line = _logFileReader.GetLogLine(i); + if (line != null) + { IList matchingList = FindMatchingHilightEntries(line); LaunchHighlightPlugins(matchingList, i); - GetHilightActions(matchingList, out suppressLed, out stopTail, out setBookmark, out bookmarkComment); + GetHilightActions(matchingList, out suppressLed, out stopTail, out setBookmark, + out bookmarkComment); if (setBookmark) { SetBookmarkFx fx = SetBookmarkFromTrigger; @@ -825,1595 +874,1533 @@ private void CheckFilterAndHighlight (LogEventArgs e) noLed = false; } } - - if (filterLineAdded) - { - //AddFilterLineGuiUpdateFx addFx = new AddFilterLineGuiUpdateFx(AddFilterLineGuiUpdate); - //this.Invoke(addFx); - TriggerFilterLineGuiUpdate(); - } - } - else - { - var firstStopTail = true; - var startLine = e.PrevLineCount; - if (e.IsRollover) - { - ShiftFilterLines(e.RolloverOffset); - startLine -= e.RolloverOffset; - } - - for (var i = startLine; i < e.LineCount; ++i) - { - ILogLine line = _logFileReader.GetLogLine(i); - if (line != null) - { - IList matchingList = FindMatchingHilightEntries(line); - LaunchHighlightPlugins(matchingList, i); - GetHilightActions(matchingList, out suppressLed, out stopTail, out setBookmark, - out bookmarkComment); - if (setBookmark) - { - SetBookmarkFx fx = SetBookmarkFromTrigger; - fx.BeginInvoke(i, bookmarkComment, null, null); - } - - if (stopTail && _guiStateArgs.FollowTail) - { - var wasFollow = _guiStateArgs.FollowTail; - FollowTailChanged(false, true); - if (firstStopTail && wasFollow) - { - Invoke(new SelectLineFx(SelectAndEnsureVisible), [i, false]); - firstStopTail = false; - } - } - - if (!suppressLed) - { - noLed = false; - } - } - } } + } - if (!noLed) - { - OnFileSizeChanged(e); - } + if (!noLed) + { + OnFileSizeChanged(e); } + } - private void LaunchHighlightPlugins (IList matchingList, int lineNum) + private void LaunchHighlightPlugins (IList matchingList, int lineNum) + { + LogExpertCallback callback = new(this) { - LogExpertCallback callback = new(this) - { - LineNum = lineNum - }; + LineNum = lineNum + }; - foreach (HighlightEntry entry in matchingList) + foreach (HighlightEntry entry in matchingList) + { + if (entry.IsActionEntry && entry.ActionEntry.PluginName != null) { - if (entry.IsActionEntry && entry.ActionEntry.PluginName != null) + IKeywordAction plugin = PluginRegistry.PluginRegistry.Instance.FindKeywordActionPluginByName(entry.ActionEntry.PluginName); + if (plugin != null) { - IKeywordAction plugin = PluginRegistry.PluginRegistry.Instance.FindKeywordActionPluginByName(entry.ActionEntry.PluginName); - if (plugin != null) - { - ActionPluginExecuteFx fx = plugin.Execute; - fx.BeginInvoke(entry.SearchText, entry.ActionEntry.ActionParam, callback, CurrentColumnizer, null, null); - } + ActionPluginExecuteFx fx = plugin.Execute; + fx.BeginInvoke(entry.SearchText, entry.ActionEntry.ActionParam, callback, CurrentColumnizer, null, null); } } } + } + + private void PreSelectColumnizer (ILogLineColumnizer columnizer) + { + CurrentColumnizer = columnizer != null + ? (_forcedColumnizerForLoading = columnizer) + : (_forcedColumnizerForLoading = ColumnizerPicker.FindColumnizer(FileName, _logFileReader, PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers)); + } + + private void SetColumnizer (ILogLineColumnizer columnizer) + { + columnizer = ColumnizerPicker.FindReplacementForAutoColumnizer(FileName, _logFileReader, columnizer, PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers); - private void PreSelectColumnizer (ILogLineColumnizer columnizer) + var timeDiff = 0; + if (CurrentColumnizer != null && CurrentColumnizer.IsTimeshiftImplemented()) { - CurrentColumnizer = columnizer != null - ? (_forcedColumnizerForLoading = columnizer) - : (_forcedColumnizerForLoading = ColumnizerPicker.FindColumnizer(FileName, _logFileReader, PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers)); + timeDiff = CurrentColumnizer.GetTimeOffset(); } - private void SetColumnizer (ILogLineColumnizer columnizer) - { - columnizer = ColumnizerPicker.FindReplacementForAutoColumnizer(FileName, _logFileReader, columnizer, PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers); + SetColumnizerInternal(columnizer); - var timeDiff = 0; - if (CurrentColumnizer != null && CurrentColumnizer.IsTimeshiftImplemented()) - { - timeDiff = CurrentColumnizer.GetTimeOffset(); - } + if (CurrentColumnizer.IsTimeshiftImplemented()) + { + CurrentColumnizer.SetTimeOffset(timeDiff); + } + } - SetColumnizerInternal(columnizer); + private void SetColumnizerInternal (ILogLineColumnizer columnizer) + { + _logger.Info("SetColumnizerInternal(): {0}", columnizer.GetName()); - if (CurrentColumnizer.IsTimeshiftImplemented()) - { - CurrentColumnizer.SetTimeOffset(timeDiff); - } - } + ILogLineColumnizer oldColumnizer = CurrentColumnizer; + var oldColumnizerIsXmlType = CurrentColumnizer is ILogLineXmlColumnizer; + var oldColumnizerIsPreProcess = CurrentColumnizer is IPreProcessColumnizer; + var mustReload = false; - private void SetColumnizerInternal (ILogLineColumnizer columnizer) + // Check if the filtered columns disappeared, if so must refresh the UI + if (_filterParams.ColumnRestrict) { - _logger.Info("SetColumnizerInternal(): {0}", columnizer.GetName()); + var newColumns = columnizer != null ? columnizer.GetColumnNames() : Array.Empty(); + var colChanged = false; - ILogLineColumnizer oldColumnizer = CurrentColumnizer; - var oldColumnizerIsXmlType = CurrentColumnizer is ILogLineXmlColumnizer; - var oldColumnizerIsPreProcess = CurrentColumnizer is IPreProcessColumnizer; - var mustReload = false; - - // Check if the filtered columns disappeared, if so must refresh the UI - if (_filterParams.ColumnRestrict) + if (dataGridView.ColumnCount - 2 == newColumns.Length) // two first columns are 'marker' and 'line number' { - var newColumns = columnizer != null ? columnizer.GetColumnNames() : Array.Empty(); - var colChanged = false; - - if (dataGridView.ColumnCount - 2 == newColumns.Length) // two first columns are 'marker' and 'line number' + for (var i = 0; i < newColumns.Length; i++) { - for (var i = 0; i < newColumns.Length; i++) + if (dataGridView.Columns[i].HeaderText != newColumns[i]) { - if (dataGridView.Columns[i].HeaderText != newColumns[i]) - { - colChanged = true; - break; // one change is sufficient - } + colChanged = true; + break; // one change is sufficient } } - else - { - colChanged = true; - } - - if (colChanged) - { - // Update UI - columnNamesLabel.Text = CalculateColumnNames(_filterParams); - } } - - Type oldColType = _filterParams.CurrentColumnizer?.GetType(); - Type newColType = columnizer?.GetType(); - - if (oldColType != newColType && _filterParams.ColumnRestrict && _filterParams.IsFilterTail) + else { - _filterParams.ColumnList.Clear(); + colChanged = true; } - if (CurrentColumnizer == null || CurrentColumnizer.GetType() != columnizer.GetType()) + if (colChanged) { - CurrentColumnizer = columnizer; - _freezeStateMap.Clear(); - if (_logFileReader != null) - { - if (CurrentColumnizer is IPreProcessColumnizer) - { - _logFileReader.PreProcessColumnizer = (IPreProcessColumnizer)CurrentColumnizer; - } - else - { - _logFileReader.PreProcessColumnizer = null; - } - } + // Update UI + columnNamesLabel.Text = CalculateColumnNames(_filterParams); + } + } - // always reload when choosing XML columnizers - if (_logFileReader != null && CurrentColumnizer is ILogLineXmlColumnizer) - { - //forcedColumnizer = currentColumnizer; // prevent Columnizer selection on SetGuiAfterReload() - mustReload = true; - } + Type oldColType = _filterParams.CurrentColumnizer?.GetType(); + Type newColType = columnizer?.GetType(); + + if (oldColType != newColType && _filterParams.ColumnRestrict && _filterParams.IsFilterTail) + { + _filterParams.ColumnList.Clear(); + } - // Reload when choosing no XML columnizer but previous columnizer was XML - if (_logFileReader != null && !(CurrentColumnizer is ILogLineXmlColumnizer) && oldColumnizerIsXmlType) + if (CurrentColumnizer == null || CurrentColumnizer.GetType() != columnizer.GetType()) + { + CurrentColumnizer = columnizer; + _freezeStateMap.Clear(); + if (_logFileReader != null) + { + if (CurrentColumnizer is IPreProcessColumnizer) { - _logFileReader.IsXmlMode = false; - //forcedColumnizer = currentColumnizer; // prevent Columnizer selection on SetGuiAfterReload() - mustReload = true; + _logFileReader.PreProcessColumnizer = (IPreProcessColumnizer)CurrentColumnizer; } - - // Reload when previous columnizer was PreProcess and current is not, and vice versa. - // When the current columnizer is a preProcess columnizer, reload in every case. - if (CurrentColumnizer is IPreProcessColumnizer != oldColumnizerIsPreProcess || - CurrentColumnizer is IPreProcessColumnizer) + else { - //forcedColumnizer = currentColumnizer; // prevent Columnizer selection on SetGuiAfterReload() - mustReload = true; + _logFileReader.PreProcessColumnizer = null; } } - else - { - CurrentColumnizer = columnizer; - } - - (oldColumnizer as IInitColumnizer)?.DeSelected(new ColumnizerCallback(this)); - - (columnizer as IInitColumnizer)?.Selected(new ColumnizerCallback(this)); - - SetColumnizer(columnizer, dataGridView); - SetColumnizer(columnizer, filterGridView); - _patternWindow?.SetColumnizer(columnizer); - - _guiStateArgs.TimeshiftPossible = columnizer.IsTimeshiftImplemented(); - SendGuiStateUpdate(); - if (_logFileReader != null) + // always reload when choosing XML columnizers + if (_logFileReader != null && CurrentColumnizer is ILogLineXmlColumnizer) { - dataGridView.RowCount = _logFileReader.LineCount; + //forcedColumnizer = currentColumnizer; // prevent Columnizer selection on SetGuiAfterReload() + mustReload = true; } - if (_filterResultList != null) + // Reload when choosing no XML columnizer but previous columnizer was XML + if (_logFileReader != null && !(CurrentColumnizer is ILogLineXmlColumnizer) && oldColumnizerIsXmlType) { - filterGridView.RowCount = _filterResultList.Count; + _logFileReader.IsXmlMode = false; + //forcedColumnizer = currentColumnizer; // prevent Columnizer selection on SetGuiAfterReload() + mustReload = true; } - if (mustReload) + // Reload when previous columnizer was PreProcess and current is not, and vice versa. + // When the current columnizer is a preProcess columnizer, reload in every case. + if (CurrentColumnizer is IPreProcessColumnizer != oldColumnizerIsPreProcess || + CurrentColumnizer is IPreProcessColumnizer) { - Reload(); + //forcedColumnizer = currentColumnizer; // prevent Columnizer selection on SetGuiAfterReload() + mustReload = true; } - else - { - if (CurrentColumnizer.IsTimeshiftImplemented()) - { - SetTimestampLimits(); - SyncTimestampDisplay(); - } + } + else + { + CurrentColumnizer = columnizer; + } - Settings settings = ConfigManager.Settings; - ShowLineColumn(!settings.hideLineColumn); - ShowTimeSpread(Preferences.showTimeSpread && columnizer.IsTimeshiftImplemented()); - } + (oldColumnizer as IInitColumnizer)?.DeSelected(new ColumnizerCallback(this)); - if (!columnizer.IsTimeshiftImplemented() && IsTimeSynced) - { - FreeFromTimeSync(); - } + (columnizer as IInitColumnizer)?.Selected(new ColumnizerCallback(this)); - columnComboBox.Items.Clear(); + SetColumnizer(columnizer, dataGridView); + SetColumnizer(columnizer, filterGridView); + _patternWindow?.SetColumnizer(columnizer); - foreach (var columnName in columnizer.GetColumnNames()) - { - columnComboBox.Items.Add(columnName); - } + _guiStateArgs.TimeshiftPossible = columnizer.IsTimeshiftImplemented(); + SendGuiStateUpdate(); - columnComboBox.SelectedIndex = 0; + if (_logFileReader != null) + { + dataGridView.RowCount = _logFileReader.LineCount; + } - OnColumnizerChanged(CurrentColumnizer); + if (_filterResultList != null) + { + filterGridView.RowCount = _filterResultList.Count; } - private void AutoResizeColumns (BufferedDataGridView gridView) + if (mustReload) { - try - { - gridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); - if (gridView.Columns.Count > 1 && Preferences.setLastColumnWidth && - gridView.Columns[gridView.Columns.Count - 1].Width < Preferences.lastColumnWidth - ) - { - // It seems that using 'MinimumWidth' instead of 'Width' prevents the DataGridView's NullReferenceExceptions - //gridView.Columns[gridView.Columns.Count - 1].Width = this.Preferences.lastColumnWidth; - gridView.Columns[gridView.Columns.Count - 1].MinimumWidth = Preferences.lastColumnWidth; - } - } - catch (NullReferenceException e) + Reload(); + } + else + { + if (CurrentColumnizer.IsTimeshiftImplemented()) { - // See https://connect.microsoft.com/VisualStudio/feedback/details/366943/autoresizecolumns-in-datagridview-throws-nullreferenceexception - // possible solution => https://stackoverflow.com/questions/36287553/nullreferenceexception-when-trying-to-set-datagridview-column-width-brings-th - // There are some rare situations with null ref exceptions when resizing columns and on filter finished - // So catch them here. Better than crashing. - _logger.Error(e, "Error while resizing columns: "); + SetTimestampLimits(); + SyncTimestampDisplay(); } + + Settings settings = ConfigManager.Settings; + ShowLineColumn(!settings.hideLineColumn); + ShowTimeSpread(Preferences.showTimeSpread && columnizer.IsTimeshiftImplemented()); } - private void PaintCell (DataGridViewCellPaintingEventArgs e, BufferedDataGridView gridView, bool noBackgroundFill, - HighlightEntry groundEntry) + if (!columnizer.IsTimeshiftImplemented() && IsTimeSynced) { - PaintHighlightedCell(e, gridView, noBackgroundFill, groundEntry); + FreeFromTimeSync(); } - private void PaintHighlightedCell (DataGridViewCellPaintingEventArgs e, BufferedDataGridView gridView, - bool noBackgroundFill, - HighlightEntry groundEntry) + columnComboBox.Items.Clear(); + + foreach (var columnName in columnizer.GetColumnNames()) { - var column = e.Value as IColumn; + columnComboBox.Items.Add(columnName); + } + + columnComboBox.SelectedIndex = 0; - column ??= Column.EmptyColumn; + OnColumnizerChanged(CurrentColumnizer); + } - IList matchList = FindHighlightMatches(column); - // too many entries per line seem to cause problems with the GDI - while (matchList.Count > 50) + private void AutoResizeColumns (BufferedDataGridView gridView) + { + try + { + gridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); + if (gridView.Columns.Count > 1 && Preferences.setLastColumnWidth && + gridView.Columns[gridView.Columns.Count - 1].Width < Preferences.lastColumnWidth + ) { - matchList.RemoveAt(50); + // It seems that using 'MinimumWidth' instead of 'Width' prevents the DataGridView's NullReferenceExceptions + //gridView.Columns[gridView.Columns.Count - 1].Width = this.Preferences.lastColumnWidth; + gridView.Columns[gridView.Columns.Count - 1].MinimumWidth = Preferences.lastColumnWidth; } + } + catch (NullReferenceException e) + { + // See https://connect.microsoft.com/VisualStudio/feedback/details/366943/autoresizecolumns-in-datagridview-throws-nullreferenceexception + // possible solution => https://stackoverflow.com/questions/36287553/nullreferenceexception-when-trying-to-set-datagridview-column-width-brings-th + // There are some rare situations with null ref exceptions when resizing columns and on filter finished + // So catch them here. Better than crashing. + _logger.Error(e, "Error while resizing columns: "); + } + } - var he = new HighlightEntry - { - SearchText = column.DisplayValue, - ForegroundColor = groundEntry?.ForegroundColor ?? Color.FromKnownColor(KnownColor.Black), - BackgroundColor = groundEntry?.BackgroundColor ?? Color.Empty, - IsWordMatch = true - }; + private void PaintCell (DataGridViewCellPaintingEventArgs e, BufferedDataGridView gridView, bool noBackgroundFill, + HighlightEntry groundEntry) + { + PaintHighlightedCell(e, gridView, noBackgroundFill, groundEntry); + } - HilightMatchEntry hme = new() - { - StartPos = 0, - Length = column.DisplayValue.Length, - HilightEntry = he - }; + private void PaintHighlightedCell (DataGridViewCellPaintingEventArgs e, BufferedDataGridView gridView, + bool noBackgroundFill, + HighlightEntry groundEntry) + { + var column = e.Value as IColumn; - if (groundEntry != null) - { - hme.HilightEntry.IsBold = groundEntry.IsBold; - } + column ??= Column.EmptyColumn; - matchList = MergeHighlightMatchEntries(matchList, hme); + IList matchList = FindHighlightMatches(column); + // too many entries per line seem to cause problems with the GDI + while (matchList.Count > 50) + { + matchList.RemoveAt(50); + } - var leftPad = e.CellStyle.Padding.Left; - RectangleF rect = new(e.CellBounds.Left + leftPad, e.CellBounds.Top, e.CellBounds.Width, - e.CellBounds.Height); - Rectangle borderWidths = PaintHelper.BorderWidths(e.AdvancedBorderStyle); - Rectangle valBounds = e.CellBounds; - valBounds.Offset(borderWidths.X, borderWidths.Y); - valBounds.Width -= borderWidths.Right; - valBounds.Height -= borderWidths.Bottom; - if (e.CellStyle.Padding != Padding.Empty) - { - valBounds.Offset(e.CellStyle.Padding.Left, e.CellStyle.Padding.Top); - valBounds.Width -= e.CellStyle.Padding.Horizontal; - valBounds.Height -= e.CellStyle.Padding.Vertical; - } + var he = new HighlightEntry + { + SearchText = column.DisplayValue, + ForegroundColor = groundEntry?.ForegroundColor ?? Color.FromKnownColor(KnownColor.Black), + BackgroundColor = groundEntry?.BackgroundColor ?? Color.Empty, + IsWordMatch = true + }; + + HilightMatchEntry hme = new() + { + StartPos = 0, + Length = column.DisplayValue.Length, + HilightEntry = he + }; - TextFormatFlags flags = - TextFormatFlags.Left - | TextFormatFlags.SingleLine - | TextFormatFlags.NoPrefix - | TextFormatFlags.PreserveGraphicsClipping - | TextFormatFlags.NoPadding - | TextFormatFlags.VerticalCenter - | TextFormatFlags.TextBoxControl - ; + if (groundEntry != null) + { + hme.HilightEntry.IsBold = groundEntry.IsBold; + } - // | TextFormatFlags.VerticalCenter - // | TextFormatFlags.TextBoxControl - // TextFormatFlags.SingleLine + matchList = MergeHighlightMatchEntries(matchList, hme); - //TextRenderer.DrawText(e.Graphics, e.Value as String, e.CellStyle.Font, valBounds, Color.FromKnownColor(KnownColor.Black), flags); + var leftPad = e.CellStyle.Padding.Left; + RectangleF rect = new(e.CellBounds.Left + leftPad, e.CellBounds.Top, e.CellBounds.Width, + e.CellBounds.Height); + Rectangle borderWidths = PaintHelper.BorderWidths(e.AdvancedBorderStyle); + Rectangle valBounds = e.CellBounds; + valBounds.Offset(borderWidths.X, borderWidths.Y); + valBounds.Width -= borderWidths.Right; + valBounds.Height -= borderWidths.Bottom; + if (e.CellStyle.Padding != Padding.Empty) + { + valBounds.Offset(e.CellStyle.Padding.Left, e.CellStyle.Padding.Top); + valBounds.Width -= e.CellStyle.Padding.Horizontal; + valBounds.Height -= e.CellStyle.Padding.Vertical; + } - Point wordPos = valBounds.Location; - Size proposedSize = new(valBounds.Width, valBounds.Height); + TextFormatFlags flags = + TextFormatFlags.Left + | TextFormatFlags.SingleLine + | TextFormatFlags.NoPrefix + | TextFormatFlags.PreserveGraphicsClipping + | TextFormatFlags.NoPadding + | TextFormatFlags.VerticalCenter + | TextFormatFlags.TextBoxControl + ; - Rectangle r = gridView.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true); - e.Graphics.SetClip(e.CellBounds); + // | TextFormatFlags.VerticalCenter + // | TextFormatFlags.TextBoxControl + // TextFormatFlags.SingleLine - foreach (HilightMatchEntry matchEntry in matchList) - { - Font font = matchEntry != null && matchEntry.HilightEntry.IsBold ? BoldFont : NormalFont; - Brush bgBrush = matchEntry.HilightEntry.BackgroundColor != Color.Empty - ? new SolidBrush(matchEntry.HilightEntry.BackgroundColor) - : null; - var matchWord = column.DisplayValue.Substring(matchEntry.StartPos, matchEntry.Length); - Size wordSize = TextRenderer.MeasureText(e.Graphics, matchWord, font, proposedSize, flags); - wordSize.Height = e.CellBounds.Height; - Rectangle wordRect = new(wordPos, wordSize); + //TextRenderer.DrawText(e.Graphics, e.Value as String, e.CellStyle.Font, valBounds, Color.FromKnownColor(KnownColor.Black), flags); - Color foreColor = matchEntry.HilightEntry.ForegroundColor; - if ((e.State & DataGridViewElementStates.Selected) != DataGridViewElementStates.Selected) - { - if (!noBackgroundFill && bgBrush != null && !matchEntry.HilightEntry.NoBackground) - { - e.Graphics.FillRectangle(bgBrush, wordRect); - } - } + Point wordPos = valBounds.Location; + Size proposedSize = new(valBounds.Width, valBounds.Height); - if (foreColor == Color.Black) + Rectangle r = gridView.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true); + e.Graphics.SetClip(e.CellBounds); + + foreach (HilightMatchEntry matchEntry in matchList) + { + Font font = matchEntry != null && matchEntry.HilightEntry.IsBold ? BoldFont : NormalFont; + Brush bgBrush = matchEntry.HilightEntry.BackgroundColor != Color.Empty + ? new SolidBrush(matchEntry.HilightEntry.BackgroundColor) + : null; + var matchWord = column.DisplayValue.Substring(matchEntry.StartPos, matchEntry.Length); + Size wordSize = TextRenderer.MeasureText(e.Graphics, matchWord, font, proposedSize, flags); + wordSize.Height = e.CellBounds.Height; + Rectangle wordRect = new(wordPos, wordSize); + + Color foreColor = matchEntry.HilightEntry.ForegroundColor; + if ((e.State & DataGridViewElementStates.Selected) != DataGridViewElementStates.Selected) + { + if (!noBackgroundFill && bgBrush != null && !matchEntry.HilightEntry.NoBackground) { - foreColor = ColorMode.ForeColor; + e.Graphics.FillRectangle(bgBrush, wordRect); } + } - TextRenderer.DrawText(e.Graphics, matchWord, font, wordRect, - foreColor, flags); - - wordPos.Offset(wordSize.Width, 0); - bgBrush?.Dispose(); + if (foreColor == Color.Black) + { + foreColor = ColorMode.ForeColor; } + + TextRenderer.DrawText(e.Graphics, matchWord, font, wordRect, + foreColor, flags); + + wordPos.Offset(wordSize.Width, 0); + bgBrush?.Dispose(); } + } - /// - /// Builds a list of HilightMatchEntry objects. A HilightMatchEntry spans over a region that is painted with the same foreground and - /// background colors. - /// All regions which don't match a word-mode entry will be painted with the colors of a default entry (groundEntry). This is either the - /// first matching non-word-mode highlight entry or a black-on-white default (if no matching entry was found). - /// - /// List of all highlight matches for the current cell - /// The entry that is used as the default. - /// List of HilightMatchEntry objects. The list spans over the whole cell and contains color infos for every substring. - private IList MergeHighlightMatchEntries (IList matchList, - HilightMatchEntry groundEntry) + /// + /// Builds a list of HilightMatchEntry objects. A HilightMatchEntry spans over a region that is painted with the same foreground and + /// background colors. + /// All regions which don't match a word-mode entry will be painted with the colors of a default entry (groundEntry). This is either the + /// first matching non-word-mode highlight entry or a black-on-white default (if no matching entry was found). + /// + /// List of all highlight matches for the current cell + /// The entry that is used as the default. + /// List of HilightMatchEntry objects. The list spans over the whole cell and contains color infos for every substring. + private IList MergeHighlightMatchEntries (IList matchList, + HilightMatchEntry groundEntry) + { + // Fill an area with lenth of whole text with a default hilight entry + var entryArray = new HighlightEntry[groundEntry.Length]; + for (var i = 0; i < entryArray.Length; ++i) { - // Fill an area with lenth of whole text with a default hilight entry - var entryArray = new HighlightEntry[groundEntry.Length]; - for (var i = 0; i < entryArray.Length; ++i) - { - entryArray[i] = groundEntry.HilightEntry; - } + entryArray[i] = groundEntry.HilightEntry; + } - // "overpaint" with all matching word match enries - // Non-word-mode matches will not overpaint because they use the groundEntry - foreach (HilightMatchEntry me in matchList) + // "overpaint" with all matching word match enries + // Non-word-mode matches will not overpaint because they use the groundEntry + foreach (HilightMatchEntry me in matchList) + { + var endPos = me.StartPos + me.Length; + for (var i = me.StartPos; i < endPos; ++i) { - var endPos = me.StartPos + me.Length; - for (var i = me.StartPos; i < endPos; ++i) + if (me.HilightEntry.IsWordMatch) { - if (me.HilightEntry.IsWordMatch) - { - entryArray[i] = me.HilightEntry; - } - else - { - //entryArray[i].ForegroundColor = me.HilightEntry.ForegroundColor; - } + entryArray[i] = me.HilightEntry; + } + else + { + //entryArray[i].ForegroundColor = me.HilightEntry.ForegroundColor; } } + } - // collect areas with same hilight entry and build new highlight match entries for it - IList mergedList = []; + // collect areas with same hilight entry and build new highlight match entries for it + IList mergedList = []; - if (entryArray.Length > 0) - { - HighlightEntry currentEntry = entryArray[0]; - var lastStartPos = 0; - var pos = 0; + if (entryArray.Length > 0) + { + HighlightEntry currentEntry = entryArray[0]; + var lastStartPos = 0; + var pos = 0; - for (; pos < entryArray.Length; ++pos) + for (; pos < entryArray.Length; ++pos) + { + if (entryArray[pos] != currentEntry) { - if (entryArray[pos] != currentEntry) + HilightMatchEntry me = new() { - HilightMatchEntry me = new() - { - StartPos = lastStartPos, - Length = pos - lastStartPos, - HilightEntry = currentEntry - }; - - mergedList.Add(me); - currentEntry = entryArray[pos]; - lastStartPos = pos; - } - } - - HilightMatchEntry me2 = new() - { - StartPos = lastStartPos, - Length = pos - lastStartPos, - HilightEntry = currentEntry - }; + StartPos = lastStartPos, + Length = pos - lastStartPos, + HilightEntry = currentEntry + }; - mergedList.Add(me2); + mergedList.Add(me); + currentEntry = entryArray[pos]; + lastStartPos = pos; + } } - return mergedList; - } + HilightMatchEntry me2 = new() + { + StartPos = lastStartPos, + Length = pos - lastStartPos, + HilightEntry = currentEntry + }; - /// - /// Returns the first HilightEntry that matches the given line - /// - private HighlightEntry FindHilightEntry (ITextValue line) - { - return FindHighlightEntry(line, false); + mergedList.Add(me2); } - private HighlightEntry FindFirstNoWordMatchHilightEntry (ITextValue line) + return mergedList; + } + + /// + /// Returns the first HilightEntry that matches the given line + /// + private HighlightEntry FindHilightEntry (ITextValue line) + { + return FindHighlightEntry(line, false); + } + + private HighlightEntry FindFirstNoWordMatchHilightEntry (ITextValue line) + { + return FindHighlightEntry(line, true); + } + + private bool CheckHighlightEntryMatch (HighlightEntry entry, ITextValue column) + { + if (entry.IsRegEx) { - return FindHighlightEntry(line, true); + //Regex rex = new Regex(entry.SearchText, entry.IsCaseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase); + if (entry.Regex.IsMatch(column.Text)) + { + return true; + } } - - private bool CheckHighlightEntryMatch (HighlightEntry entry, ITextValue column) + else { - if (entry.IsRegEx) + if (entry.IsCaseSensitive) { - //Regex rex = new Regex(entry.SearchText, entry.IsCaseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase); - if (entry.Regex.IsMatch(column.Text)) + if (column.Text.Contains(entry.SearchText)) { return true; } } else { - if (entry.IsCaseSensitive) - { - if (column.Text.Contains(entry.SearchText)) - { - return true; - } - } - else + if (column.Text.ToLower().Contains(entry.SearchText.ToLower())) { - if (column.Text.ToLower().Contains(entry.SearchText.ToLower())) - { - return true; - } + return true; } } - - return false; } - /// - /// Returns all HilightEntry entries which matches the given line - /// - private IList FindMatchingHilightEntries (ITextValue line) + return false; + } + + /// + /// Returns all HilightEntry entries which matches the given line + /// + private IList FindMatchingHilightEntries (ITextValue line) + { + IList resultList = []; + if (line != null) { - IList resultList = []; - if (line != null) + lock (_currentHighlightGroupLock) { - lock (_currentHighlightGroupLock) + foreach (HighlightEntry entry in _currentHighlightGroup.HighlightEntryList) { - foreach (HighlightEntry entry in _currentHighlightGroup.HighlightEntryList) + if (CheckHighlightEntryMatch(entry, line)) { - if (CheckHighlightEntryMatch(entry, line)) - { - resultList.Add(entry); - } + resultList.Add(entry); } } } - - return resultList; } - private void GetHighlightEntryMatches (ITextValue line, IList hilightEntryList, IList resultList) + return resultList; + } + + private void GetHighlightEntryMatches (ITextValue line, IList hilightEntryList, IList resultList) + { + foreach (HighlightEntry entry in hilightEntryList) { - foreach (HighlightEntry entry in hilightEntryList) + if (entry.IsWordMatch) { - if (entry.IsWordMatch) + MatchCollection matches = entry.Regex.Matches(line.Text); + foreach (Match match in matches) { - MatchCollection matches = entry.Regex.Matches(line.Text); - foreach (Match match in matches) - { - HilightMatchEntry me = new(); - me.HilightEntry = entry; - me.StartPos = match.Index; - me.Length = match.Length; - resultList.Add(me); - } + HilightMatchEntry me = new(); + me.HilightEntry = entry; + me.StartPos = match.Index; + me.Length = match.Length; + resultList.Add(me); } - else + } + else + { + if (CheckHighlightEntryMatch(entry, line)) { - if (CheckHighlightEntryMatch(entry, line)) - { - HilightMatchEntry me = new(); - me.HilightEntry = entry; - me.StartPos = 0; - me.Length = line.Text.Length; - resultList.Add(me); - } + HilightMatchEntry me = new(); + me.HilightEntry = entry; + me.StartPos = 0; + me.Length = line.Text.Length; + resultList.Add(me); } } } + } - private void GetHilightActions (IList matchingList, out bool noLed, out bool stopTail, - out bool setBookmark, out string bookmarkComment) - { - noLed = stopTail = setBookmark = false; - bookmarkComment = string.Empty; + private void GetHilightActions (IList matchingList, out bool noLed, out bool stopTail, + out bool setBookmark, out string bookmarkComment) + { + noLed = stopTail = setBookmark = false; + bookmarkComment = string.Empty; - foreach (HighlightEntry entry in matchingList) + foreach (HighlightEntry entry in matchingList) + { + if (entry.IsLedSwitch) { - if (entry.IsLedSwitch) - { - noLed = true; - } - - if (entry.IsSetBookmark) - { - setBookmark = true; - if (!string.IsNullOrEmpty(entry.BookmarkComment)) - { - bookmarkComment += entry.BookmarkComment + "\r\n"; - } - } + noLed = true; + } - if (entry.IsStopTail) + if (entry.IsSetBookmark) + { + setBookmark = true; + if (!string.IsNullOrEmpty(entry.BookmarkComment)) { - stopTail = true; + bookmarkComment += entry.BookmarkComment + "\r\n"; } } - bookmarkComment = bookmarkComment.TrimEnd(['\r', '\n']); + if (entry.IsStopTail) + { + stopTail = true; + } } - private void StopTimespreadThread () - { - _timeSpreadCalc.Stop(); - } + bookmarkComment = bookmarkComment.TrimEnd(['\r', '\n']); + } - private void StopTimestampSyncThread () - { - _shouldTimestampDisplaySyncingCancel = true; - //_timeShiftSyncWakeupEvent.Set(); - //_timeShiftSyncThread.Abort(); - //_timeShiftSyncThread.Join(); - cts.Cancel(); - } + private void StopTimespreadThread () + { + _timeSpreadCalc.Stop(); + } + + private void StopTimestampSyncThread () + { + _shouldTimestampDisplaySyncingCancel = true; + //_timeShiftSyncWakeupEvent.Set(); + //_timeShiftSyncThread.Abort(); + //_timeShiftSyncThread.Join(); + cts.Cancel(); + } - private void SyncTimestampDisplay () + private void SyncTimestampDisplay () + { + if (CurrentColumnizer.IsTimeshiftImplemented()) { - if (CurrentColumnizer.IsTimeshiftImplemented()) + if (dataGridView.CurrentRow != null) { - if (dataGridView.CurrentRow != null) - { - SyncTimestampDisplay(dataGridView.CurrentRow.Index); - } + SyncTimestampDisplay(dataGridView.CurrentRow.Index); } } + } - private void SyncTimestampDisplay (int lineNum) - { - _timeShiftSyncLine = lineNum; - _timeShiftSyncTimerEvent.Set(); - _timeShiftSyncWakeupEvent.Set(); - } + private void SyncTimestampDisplay (int lineNum) + { + _timeShiftSyncLine = lineNum; + _timeShiftSyncTimerEvent.Set(); + _timeShiftSyncWakeupEvent.Set(); + } + + private void SyncTimestampDisplayWorker () + { + const int WAIT_TIME = 500; + Thread.CurrentThread.Name = "SyncTimestampDisplayWorker"; + _shouldTimestampDisplaySyncingCancel = false; + _isTimestampDisplaySyncing = true; - private void SyncTimestampDisplayWorker () + while (!_shouldTimestampDisplaySyncingCancel) { - const int WAIT_TIME = 500; - Thread.CurrentThread.Name = "SyncTimestampDisplayWorker"; - _shouldTimestampDisplaySyncingCancel = false; - _isTimestampDisplaySyncing = true; + _timeShiftSyncWakeupEvent.WaitOne(); + if (_shouldTimestampDisplaySyncingCancel) + { + return; + } + + _timeShiftSyncWakeupEvent.Reset(); while (!_shouldTimestampDisplaySyncingCancel) { - _timeShiftSyncWakeupEvent.WaitOne(); - if (_shouldTimestampDisplaySyncingCancel) + var signaled = _timeShiftSyncTimerEvent.WaitOne(WAIT_TIME, true); + _timeShiftSyncTimerEvent.Reset(); + if (!signaled) { - return; + break; } + } - _timeShiftSyncWakeupEvent.Reset(); - - while (!_shouldTimestampDisplaySyncingCancel) + // timeout with no new Trigger -> update display + var lineNum = _timeShiftSyncLine; + if (lineNum >= 0 && lineNum < dataGridView.RowCount) + { + var refLine = lineNum; + DateTime timeStamp = GetTimestampForLine(ref refLine, true); + if (!timeStamp.Equals(DateTime.MinValue) && !_shouldTimestampDisplaySyncingCancel) { - var signaled = _timeShiftSyncTimerEvent.WaitOne(WAIT_TIME, true); - _timeShiftSyncTimerEvent.Reset(); - if (!signaled) + _guiStateArgs.Timestamp = timeStamp; + SendGuiStateUpdate(); + if (_shouldCallTimeSync) { - break; + refLine = lineNum; + DateTime exactTimeStamp = GetTimestampForLine(ref refLine, false); + SyncOtherWindows(exactTimeStamp); + _shouldCallTimeSync = false; } } + } - // timeout with no new Trigger -> update display - var lineNum = _timeShiftSyncLine; - if (lineNum >= 0 && lineNum < dataGridView.RowCount) + // show time difference between 2 selected lines + if (dataGridView.SelectedRows.Count == 2) + { + var row1 = dataGridView.SelectedRows[0].Index; + var row2 = dataGridView.SelectedRows[1].Index; + if (row1 > row2) { - var refLine = lineNum; - DateTime timeStamp = GetTimestampForLine(ref refLine, true); - if (!timeStamp.Equals(DateTime.MinValue) && !_shouldTimestampDisplaySyncingCancel) - { - _guiStateArgs.Timestamp = timeStamp; - SendGuiStateUpdate(); - if (_shouldCallTimeSync) - { - refLine = lineNum; - DateTime exactTimeStamp = GetTimestampForLine(ref refLine, false); - SyncOtherWindows(exactTimeStamp); - _shouldCallTimeSync = false; - } - } + (row2, row1) = (row1, row2); } - // show time difference between 2 selected lines - if (dataGridView.SelectedRows.Count == 2) + var refLine = row1; + DateTime timeStamp1 = GetTimestampForLine(ref refLine, false); + refLine = row2; + DateTime timeStamp2 = GetTimestampForLine(ref refLine, false); + //TimeSpan span = TimeSpan.FromTicks(timeStamp2.Ticks - timeStamp1.Ticks); + DateTime diff; + if (timeStamp1.Ticks > timeStamp2.Ticks) { - var row1 = dataGridView.SelectedRows[0].Index; - var row2 = dataGridView.SelectedRows[1].Index; - if (row1 > row2) - { - (row2, row1) = (row1, row2); - } - - var refLine = row1; - DateTime timeStamp1 = GetTimestampForLine(ref refLine, false); - refLine = row2; - DateTime timeStamp2 = GetTimestampForLine(ref refLine, false); - //TimeSpan span = TimeSpan.FromTicks(timeStamp2.Ticks - timeStamp1.Ticks); - DateTime diff; - if (timeStamp1.Ticks > timeStamp2.Ticks) - { - diff = new DateTime(timeStamp1.Ticks - timeStamp2.Ticks); - } - else - { - diff = new DateTime(timeStamp2.Ticks - timeStamp1.Ticks); - } - - StatusLineText("Time diff is " + diff.ToString("HH:mm:ss.fff")); + diff = new DateTime(timeStamp1.Ticks - timeStamp2.Ticks); } else { - if (!IsMultiFile && dataGridView.SelectedRows.Count == 1) - { - StatusLineText(string.Empty); - } + diff = new DateTime(timeStamp2.Ticks - timeStamp1.Ticks); + } + + StatusLineText("Time diff is " + diff.ToString("HH:mm:ss.fff")); + } + else + { + if (!IsMultiFile && dataGridView.SelectedRows.Count == 1) + { + StatusLineText(string.Empty); } } } + } - private void SyncFilterGridPos () + private void SyncFilterGridPos () + { + try { - try + if (_filterResultList.Count > 0) { - if (_filterResultList.Count > 0) + var index = _filterResultList.BinarySearch(dataGridView.CurrentRow.Index); + if (index < 0) { - var index = _filterResultList.BinarySearch(dataGridView.CurrentRow.Index); - if (index < 0) + index = ~index; + if (index > 0) { - index = ~index; - if (index > 0) - { - --index; - } + --index; } + } - if (filterGridView.Rows.GetRowCount(DataGridViewElementStates.None) > 0) // exception no rows - { - filterGridView.CurrentCell = filterGridView.Rows[index].Cells[0]; - } - else - { - filterGridView.CurrentCell = null; - } + if (filterGridView.Rows.GetRowCount(DataGridViewElementStates.None) > 0) // exception no rows + { + filterGridView.CurrentCell = filterGridView.Rows[index].Cells[0]; + } + else + { + filterGridView.CurrentCell = null; } - } - catch (Exception e) - { - _logger.Error(e, "SyncFilterGridPos(): "); } } - - private void StatusLineFileSize (long size) + catch (Exception e) { - _statusEventArgs.FileSize = size; - SendStatusLineUpdate(); + _logger.Error(e, "SyncFilterGridPos(): "); } + } + + private void StatusLineFileSize (long size) + { + _statusEventArgs.FileSize = size; + SendStatusLineUpdate(); + } - private int Search (SearchParams searchParams) + private int Search (SearchParams searchParams) + { + if (searchParams.SearchText == null) { - if (searchParams.SearchText == null) - { - return -1; - } + return -1; + } - var lineNum = searchParams.IsFromTop && !searchParams.IsFindNext - ? 0 - : searchParams.CurrentLine; + var lineNum = searchParams.IsFromTop && !searchParams.IsFindNext + ? 0 + : searchParams.CurrentLine; - var lowerSearchText = searchParams.SearchText.ToLower(); - var count = 0; - var hasWrapped = false; + var lowerSearchText = searchParams.SearchText.ToLower(); + var count = 0; + var hasWrapped = false; - while (true) + while (true) + { + if ((searchParams.IsForward || searchParams.IsFindNext) && !searchParams.IsShiftF3Pressed) { - if ((searchParams.IsForward || searchParams.IsFindNext) && !searchParams.IsShiftF3Pressed) + if (lineNum >= _logFileReader.LineCount) { - if (lineNum >= _logFileReader.LineCount) + if (hasWrapped) { - if (hasWrapped) - { - StatusLineError("Not found: " + searchParams.SearchText); - return -1; - } - - lineNum = 0; - count = 0; - hasWrapped = true; - StatusLineError("Started from beginning of file"); + StatusLineError("Not found: " + searchParams.SearchText); + return -1; } + + lineNum = 0; + count = 0; + hasWrapped = true; + StatusLineError("Started from beginning of file"); } - else + } + else + { + if (lineNum < 0) { - if (lineNum < 0) + if (hasWrapped) { - if (hasWrapped) - { - StatusLineError("Not found: " + searchParams.SearchText); - return -1; - } - - count = 0; - lineNum = _logFileReader.LineCount - 1; - hasWrapped = true; - StatusLineError("Started from end of file"); + StatusLineError("Not found: " + searchParams.SearchText); + return -1; } + + count = 0; + lineNum = _logFileReader.LineCount - 1; + hasWrapped = true; + StatusLineError("Started from end of file"); } + } - ILogLine line = _logFileReader.GetLogLine(lineNum); - if (line == null) + ILogLine line = _logFileReader.GetLogLine(lineNum); + if (line == null) + { + return -1; + } + + if (searchParams.IsRegex) + { + Regex rex = new(searchParams.SearchText, searchParams.IsCaseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase); + if (rex.IsMatch(line.FullLine)) { - return -1; + return lineNum; } - - if (searchParams.IsRegex) + } + else + { + if (!searchParams.IsCaseSensitive) { - Regex rex = new(searchParams.SearchText, searchParams.IsCaseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase); - if (rex.IsMatch(line.FullLine)) + if (line.FullLine.Contains(lowerSearchText, StringComparison.CurrentCultureIgnoreCase)) { return lineNum; } } else { - if (!searchParams.IsCaseSensitive) - { - if (line.FullLine.Contains(lowerSearchText, StringComparison.CurrentCultureIgnoreCase)) - { - return lineNum; - } - } - else + if (line.FullLine.Contains(searchParams.SearchText)) { - if (line.FullLine.Contains(searchParams.SearchText)) - { - return lineNum; - } + return lineNum; } } + } - if ((searchParams.IsForward || searchParams.IsFindNext) && !searchParams.IsShiftF3Pressed) - { - lineNum++; - } - else - { - lineNum--; - } + if ((searchParams.IsForward || searchParams.IsFindNext) && !searchParams.IsShiftF3Pressed) + { + lineNum++; + } + else + { + lineNum--; + } - if (_shouldCancel) - { - return -1; - } + if (_shouldCancel) + { + return -1; + } - if (++count % PROGRESS_BAR_MODULO == 0) + if (++count % PROGRESS_BAR_MODULO == 0) + { + try { - try - { - if (!Disposing) - { - Invoke(UpdateProgressBar, [count]); - } - } - catch (ObjectDisposedException ex) // can occur when closing the app while searching + if (!Disposing) { - _logger.Warn(ex); + Invoke(UpdateProgressBar, [count]); } } + catch (ObjectDisposedException ex) // can occur when closing the app while searching + { + _logger.Warn(ex); + } } } + } - private void ResetProgressBar () - { - _progressEventArgs.Value = _progressEventArgs.MaxValue; - _progressEventArgs.Visible = false; - SendProgressBarUpdate(); - } + private void ResetProgressBar () + { + _progressEventArgs.Value = _progressEventArgs.MaxValue; + _progressEventArgs.Visible = false; + SendProgressBarUpdate(); + } - private void SelectLine (int line, bool triggerSyncCall, bool shouldScroll) + private void SelectLine (int line, bool triggerSyncCall, bool shouldScroll) + { + try { - try - { - _shouldCallTimeSync = triggerSyncCall; - var wasCancelled = _shouldCancel; - _shouldCancel = false; - _isSearching = false; - StatusLineText(""); - _guiStateArgs.MenuEnabled = true; - - if (wasCancelled) - { - return; - } - - if (line == -1) - { - // Hmm... is that experimental code from early days? - MessageBox.Show(this, "Not found:", "Search result"); - return; - } - - // Prevent ArgumentOutOfRangeException - if (line >= dataGridView.Rows.GetRowCount(DataGridViewElementStates.None)) - { - line = dataGridView.Rows.GetRowCount(DataGridViewElementStates.None) - 1; - } + _shouldCallTimeSync = triggerSyncCall; + var wasCancelled = _shouldCancel; + _shouldCancel = false; + _isSearching = false; + StatusLineText(""); + _guiStateArgs.MenuEnabled = true; - dataGridView.Rows[line].Selected = true; + if (wasCancelled) + { + return; + } - if (shouldScroll) - { - dataGridView.CurrentCell = dataGridView.Rows[line].Cells[0]; - dataGridView.Focus(); - } + if (line == -1) + { + // Hmm... is that experimental code from early days? + MessageBox.Show(this, "Not found:", "Search result"); + return; } - catch (ArgumentOutOfRangeException e) + + // Prevent ArgumentOutOfRangeException + if (line >= dataGridView.Rows.GetRowCount(DataGridViewElementStates.None)) { - _logger.Error(e, "Error while selecting line: "); + line = dataGridView.Rows.GetRowCount(DataGridViewElementStates.None) - 1; } - catch (IndexOutOfRangeException e) + + dataGridView.Rows[line].Selected = true; + + if (shouldScroll) { - // Occures sometimes (but cannot reproduce) - _logger.Error(e, "Error while selecting line: "); + dataGridView.CurrentCell = dataGridView.Rows[line].Cells[0]; + dataGridView.Focus(); } } + catch (ArgumentOutOfRangeException e) + { + _logger.Error(e, "Error while selecting line: "); + } + catch (IndexOutOfRangeException e) + { + // Occures sometimes (but cannot reproduce) + _logger.Error(e, "Error while selecting line: "); + } + } - private void StartEditMode () + private void StartEditMode () + { + if (!dataGridView.CurrentCell.ReadOnly) { - if (!dataGridView.CurrentCell.ReadOnly) + dataGridView.BeginEdit(false); + if (dataGridView.EditingControl != null) { - dataGridView.BeginEdit(false); - if (dataGridView.EditingControl != null) + if (dataGridView.EditingControl is LogCellEditingControl editControl) { - if (dataGridView.EditingControl is LogCellEditingControl editControl) - { - editControl.KeyDown += OnEditControlKeyDown; - editControl.KeyPress += OnEditControlKeyPress; - editControl.KeyUp += OnEditControlKeyUp; - editControl.Click += OnEditControlClick; - dataGridView.CellEndEdit += OnDataGridViewCellEndEdit; - editControl.SelectionStart = 0; - } - else - { - _logger.Warn("Edit control in logWindow was null"); - } + editControl.KeyDown += OnEditControlKeyDown; + editControl.KeyPress += OnEditControlKeyPress; + editControl.KeyUp += OnEditControlKeyUp; + editControl.Click += OnEditControlClick; + dataGridView.CellEndEdit += OnDataGridViewCellEndEdit; + editControl.SelectionStart = 0; + } + else + { + _logger.Warn("Edit control in logWindow was null"); } } } + } - private void UpdateEditColumnDisplay (DataGridViewTextBoxEditingControl editControl) + private void UpdateEditColumnDisplay (DataGridViewTextBoxEditingControl editControl) + { + // prevents key events after edit mode has ended + if (dataGridView.EditingControl != null) { - // prevents key events after edit mode has ended - if (dataGridView.EditingControl != null) - { - var pos = editControl.SelectionStart + editControl.SelectionLength; - StatusLineText(" " + pos); - _logger.Debug("SelStart: {0}, SelLen: {1}", editControl.SelectionStart, editControl.SelectionLength); - } + var pos = editControl.SelectionStart + editControl.SelectionLength; + StatusLineText(" " + pos); + _logger.Debug("SelStart: {0}, SelLen: {1}", editControl.SelectionStart, editControl.SelectionLength); } + } - private void SelectPrevHighlightLine () + private void SelectPrevHighlightLine () + { + var lineNum = dataGridView.CurrentCellAddress.Y; + while (lineNum > 0) { - var lineNum = dataGridView.CurrentCellAddress.Y; - while (lineNum > 0) + lineNum--; + ILogLine line = _logFileReader.GetLogLine(lineNum); + if (line != null) { - lineNum--; - ILogLine line = _logFileReader.GetLogLine(lineNum); - if (line != null) + HighlightEntry entry = FindHilightEntry(line); + if (entry != null) { - HighlightEntry entry = FindHilightEntry(line); - if (entry != null) - { - SelectLine(lineNum, false, true); - break; - } + SelectLine(lineNum, false, true); + break; } } } + } - private void SelectNextHighlightLine () + private void SelectNextHighlightLine () + { + var lineNum = dataGridView.CurrentCellAddress.Y; + while (lineNum < _logFileReader.LineCount) { - var lineNum = dataGridView.CurrentCellAddress.Y; - while (lineNum < _logFileReader.LineCount) + lineNum++; + ILogLine line = _logFileReader.GetLogLine(lineNum); + if (line != null) { - lineNum++; - ILogLine line = _logFileReader.GetLogLine(lineNum); - if (line != null) + HighlightEntry entry = FindHilightEntry(line); + if (entry != null) { - HighlightEntry entry = FindHilightEntry(line); - if (entry != null) - { - SelectLine(lineNum, false, true); - break; - } + SelectLine(lineNum, false, true); + break; } } } + } - private int FindNextBookmarkIndex (int lineNum) + private int FindNextBookmarkIndex (int lineNum) + { + if (lineNum >= dataGridView.RowCount) { - if (lineNum >= dataGridView.RowCount) - { - lineNum = 0; - } - else - { - lineNum++; - } - - return _bookmarkProvider.FindNextBookmarkIndex(lineNum); + lineNum = 0; } - - private int FindPrevBookmarkIndex (int lineNum) + else { - if (lineNum <= 0) - { - lineNum = dataGridView.RowCount - 1; - } - else - { - lineNum--; - } - - return _bookmarkProvider.FindPrevBookmarkIndex(lineNum); + lineNum++; } - /** - * Shift bookmarks after a logfile rollover - */ + return _bookmarkProvider.FindNextBookmarkIndex(lineNum); + } - private void ShiftBookmarks (int offset) + private int FindPrevBookmarkIndex (int lineNum) + { + if (lineNum <= 0) + { + lineNum = dataGridView.RowCount - 1; + } + else { - _bookmarkProvider.ShiftBookmarks(offset); - OnBookmarkRemoved(); + lineNum--; } - private void ShiftRowHeightList (int offset) + return _bookmarkProvider.FindPrevBookmarkIndex(lineNum); + } + + /** + * Shift bookmarks after a logfile rollover + */ + + private void ShiftBookmarks (int offset) + { + _bookmarkProvider.ShiftBookmarks(offset); + OnBookmarkRemoved(); + } + + private void ShiftRowHeightList (int offset) + { + SortedList newList = []; + foreach (RowHeightEntry entry in _rowHeightList.Values) { - SortedList newList = []; - foreach (RowHeightEntry entry in _rowHeightList.Values) + var line = entry.LineNum - offset; + if (line >= 0) { - var line = entry.LineNum - offset; - if (line >= 0) - { - entry.LineNum = line; - newList.Add(line, entry); - } + entry.LineNum = line; + newList.Add(line, entry); } - - _rowHeightList = newList; } - private void ShiftFilterPipes (int offset) + _rowHeightList = newList; + } + + private void ShiftFilterPipes (int offset) + { + lock (_filterPipeList) { - lock (_filterPipeList) + foreach (FilterPipe pipe in _filterPipeList) { - foreach (FilterPipe pipe in _filterPipeList) - { - pipe.ShiftLineNums(offset); - } + pipe.ShiftLineNums(offset); } } + } - private void LoadFilterPipes () + private void LoadFilterPipes () + { + lock (_filterPipeList) { - lock (_filterPipeList) + foreach (FilterPipe pipe in _filterPipeList) { - foreach (FilterPipe pipe in _filterPipeList) - { - pipe.RecreateTempFile(); - } + pipe.RecreateTempFile(); } + } - if (_filterPipeList.Count > 0) + if (_filterPipeList.Count > 0) + { + for (var i = 0; i < dataGridView.RowCount; ++i) { - for (var i = 0; i < dataGridView.RowCount; ++i) - { - ProcessFilterPipes(i); - } + ProcessFilterPipes(i); } } + } - private void DisconnectFilterPipes () + private void DisconnectFilterPipes () + { + lock (_filterPipeList) { - lock (_filterPipeList) + foreach (FilterPipe pipe in _filterPipeList) { - foreach (FilterPipe pipe in _filterPipeList) - { - pipe.ClearLineList(); - } + pipe.ClearLineList(); } } + } - private void ApplyFilterParams () - { - filterComboBox.Text = _filterParams.SearchText; - filterCaseSensitiveCheckBox.Checked = _filterParams.IsCaseSensitive; - filterRegexCheckBox.Checked = _filterParams.IsRegex; - filterTailCheckBox.Checked = _filterParams.IsFilterTail; - invertFilterCheckBox.Checked = _filterParams.IsInvert; - filterKnobBackSpread.Value = _filterParams.SpreadBefore; - filterKnobForeSpread.Value = _filterParams.SpreadBehind; - rangeCheckBox.Checked = _filterParams.IsRangeSearch; - columnRestrictCheckBox.Checked = _filterParams.ColumnRestrict; - fuzzyKnobControl.Value = _filterParams.FuzzyValue; - filterRangeComboBox.Text = _filterParams.RangeSearchText; - } + private void ApplyFilterParams () + { + filterComboBox.Text = _filterParams.SearchText; + filterCaseSensitiveCheckBox.Checked = _filterParams.IsCaseSensitive; + filterRegexCheckBox.Checked = _filterParams.IsRegex; + filterTailCheckBox.Checked = _filterParams.IsFilterTail; + invertFilterCheckBox.Checked = _filterParams.IsInvert; + filterKnobBackSpread.Value = _filterParams.SpreadBefore; + filterKnobForeSpread.Value = _filterParams.SpreadBehind; + rangeCheckBox.Checked = _filterParams.IsRangeSearch; + columnRestrictCheckBox.Checked = _filterParams.ColumnRestrict; + fuzzyKnobControl.Value = _filterParams.FuzzyValue; + filterRangeComboBox.Text = _filterParams.RangeSearchText; + } - private void ResetFilterControls () + private void ResetFilterControls () + { + filterComboBox.Text = ""; + filterCaseSensitiveCheckBox.Checked = false; + filterRegexCheckBox.Checked = false; + //this.filterTailCheckBox.Checked = this.Preferences.filterTail; + invertFilterCheckBox.Checked = false; + filterKnobBackSpread.Value = 0; + filterKnobForeSpread.Value = 0; + rangeCheckBox.Checked = false; + columnRestrictCheckBox.Checked = false; + fuzzyKnobControl.Value = 0; + filterRangeComboBox.Text = ""; + } + + private void FilterSearch () + { + if (filterComboBox.Text.Length == 0) { - filterComboBox.Text = ""; - filterCaseSensitiveCheckBox.Checked = false; - filterRegexCheckBox.Checked = false; - //this.filterTailCheckBox.Checked = this.Preferences.filterTail; - invertFilterCheckBox.Checked = false; - filterKnobBackSpread.Value = 0; - filterKnobForeSpread.Value = 0; - rangeCheckBox.Checked = false; - columnRestrictCheckBox.Checked = false; - fuzzyKnobControl.Value = 0; - filterRangeComboBox.Text = ""; + _filterParams.SearchText = ""; + _filterParams.LowerSearchText = ""; + _filterParams.IsRangeSearch = false; + ClearFilterList(); + filterSearchButton.Image = null; + ResetFilterControls(); + saveFilterButton.Enabled = false; + return; } - private void FilterSearch () - { - if (filterComboBox.Text.Length == 0) - { - _filterParams.SearchText = ""; - _filterParams.LowerSearchText = ""; - _filterParams.IsRangeSearch = false; - ClearFilterList(); - filterSearchButton.Image = null; - ResetFilterControls(); - saveFilterButton.Enabled = false; - return; - } + FilterSearch(filterComboBox.Text); + } - FilterSearch(filterComboBox.Text); + private async void FilterSearch (string text) + { + FireCancelHandlers(); // make sure that there's no other filter running (maybe from filter restore) + + _filterParams.SearchText = text; + _filterParams.LowerSearchText = text.ToLower(); + ConfigManager.Settings.filterHistoryList.Remove(text); + ConfigManager.Settings.filterHistoryList.Insert(0, text); + var maxHistory = ConfigManager.Settings.Preferences.maximumFilterEntries; + + if (ConfigManager.Settings.filterHistoryList.Count > maxHistory) + { + ConfigManager.Settings.filterHistoryList.RemoveAt(filterComboBox.Items.Count - 1); } - private async void FilterSearch (string text) + filterComboBox.Items.Clear(); + foreach (var item in ConfigManager.Settings.filterHistoryList) { - FireCancelHandlers(); // make sure that there's no other filter running (maybe from filter restore) + filterComboBox.Items.Add(item); + } - _filterParams.SearchText = text; - _filterParams.LowerSearchText = text.ToLower(); - ConfigManager.Settings.filterHistoryList.Remove(text); - ConfigManager.Settings.filterHistoryList.Insert(0, text); - var maxHistory = ConfigManager.Settings.Preferences.maximumFilterEntries; + filterComboBox.Text = text; - if (ConfigManager.Settings.filterHistoryList.Count > maxHistory) + _filterParams.IsRangeSearch = rangeCheckBox.Checked; + _filterParams.RangeSearchText = filterRangeComboBox.Text; + if (_filterParams.IsRangeSearch) + { + ConfigManager.Settings.filterRangeHistoryList.Remove(filterRangeComboBox.Text); + ConfigManager.Settings.filterRangeHistoryList.Insert(0, filterRangeComboBox.Text); + if (ConfigManager.Settings.filterRangeHistoryList.Count > maxHistory) { - ConfigManager.Settings.filterHistoryList.RemoveAt(filterComboBox.Items.Count - 1); + ConfigManager.Settings.filterRangeHistoryList.RemoveAt(filterRangeComboBox.Items.Count - 1); } - filterComboBox.Items.Clear(); - foreach (var item in ConfigManager.Settings.filterHistoryList) + filterRangeComboBox.Items.Clear(); + foreach (var item in ConfigManager.Settings.filterRangeHistoryList) { - filterComboBox.Items.Add(item); + filterRangeComboBox.Items.Add(item); } + } - filterComboBox.Text = text; + ConfigManager.Save(SettingsFlags.FilterHistory); - _filterParams.IsRangeSearch = rangeCheckBox.Checked; - _filterParams.RangeSearchText = filterRangeComboBox.Text; - if (_filterParams.IsRangeSearch) + _filterParams.IsCaseSensitive = filterCaseSensitiveCheckBox.Checked; + _filterParams.IsRegex = filterRegexCheckBox.Checked; + _filterParams.IsFilterTail = filterTailCheckBox.Checked; + _filterParams.IsInvert = invertFilterCheckBox.Checked; + if (_filterParams.IsRegex) + { + try { - ConfigManager.Settings.filterRangeHistoryList.Remove(filterRangeComboBox.Text); - ConfigManager.Settings.filterRangeHistoryList.Insert(0, filterRangeComboBox.Text); - if (ConfigManager.Settings.filterRangeHistoryList.Count > maxHistory) - { - ConfigManager.Settings.filterRangeHistoryList.RemoveAt(filterRangeComboBox.Items.Count - 1); - } - - filterRangeComboBox.Items.Clear(); - foreach (var item in ConfigManager.Settings.filterRangeHistoryList) - { - filterRangeComboBox.Items.Add(item); - } + _filterParams.CreateRegex(); } - - ConfigManager.Save(SettingsFlags.FilterHistory); - - _filterParams.IsCaseSensitive = filterCaseSensitiveCheckBox.Checked; - _filterParams.IsRegex = filterRegexCheckBox.Checked; - _filterParams.IsFilterTail = filterTailCheckBox.Checked; - _filterParams.IsInvert = invertFilterCheckBox.Checked; - if (_filterParams.IsRegex) + catch (ArgumentException) { - try - { - _filterParams.CreateRegex(); - } - catch (ArgumentException) - { - StatusLineError("Invalid regular expression"); - return; - } + StatusLineError("Invalid regular expression"); + return; } + } - _filterParams.FuzzyValue = fuzzyKnobControl.Value; - _filterParams.SpreadBefore = filterKnobBackSpread.Value; - _filterParams.SpreadBehind = filterKnobForeSpread.Value; - _filterParams.ColumnRestrict = columnRestrictCheckBox.Checked; + _filterParams.FuzzyValue = fuzzyKnobControl.Value; + _filterParams.SpreadBefore = filterKnobBackSpread.Value; + _filterParams.SpreadBehind = filterKnobForeSpread.Value; + _filterParams.ColumnRestrict = columnRestrictCheckBox.Checked; - //ConfigManager.SaveFilterParams(this.filterParams); - ConfigManager.Settings.filterParams = _filterParams; // wozu eigentlich? sinnlos seit MDI? + //ConfigManager.SaveFilterParams(this.filterParams); + ConfigManager.Settings.filterParams = _filterParams; // wozu eigentlich? sinnlos seit MDI? - _shouldCancel = false; - _isSearching = true; - StatusLineText("Filtering... Press ESC to cancel"); - filterSearchButton.Enabled = false; - ClearFilterList(); + _shouldCancel = false; + _isSearching = true; + StatusLineText("Filtering... Press ESC to cancel"); + filterSearchButton.Enabled = false; + ClearFilterList(); - _progressEventArgs.MinValue = 0; - _progressEventArgs.MaxValue = dataGridView.RowCount; - _progressEventArgs.Value = 0; - _progressEventArgs.Visible = true; - SendProgressBarUpdate(); + _progressEventArgs.MinValue = 0; + _progressEventArgs.MaxValue = dataGridView.RowCount; + _progressEventArgs.Value = 0; + _progressEventArgs.Visible = true; + SendProgressBarUpdate(); - Settings settings = ConfigManager.Settings; + Settings settings = ConfigManager.Settings; - //FilterFx fx = settings.preferences.multiThreadFilter ? MultiThreadedFilter : new FilterFx(Filter); - FilterFxAction = settings.Preferences.multiThreadFilter ? MultiThreadedFilter : Filter; + //FilterFx fx = settings.preferences.multiThreadFilter ? MultiThreadedFilter : new FilterFx(Filter); + FilterFxAction = settings.Preferences.multiThreadFilter ? MultiThreadedFilter : Filter; - //Task.Run(() => fx.Invoke(_filterParams, _filterResultList, _lastFilterLinesList, _filterHitList)); - var filterFxActionTask = Task.Run(() => Filter(_filterParams, _filterResultList, _lastFilterLinesList, _filterHitList)); + //Task.Run(() => fx.Invoke(_filterParams, _filterResultList, _lastFilterLinesList, _filterHitList)); + var filterFxActionTask = Task.Run(() => Filter(_filterParams, _filterResultList, _lastFilterLinesList, _filterHitList)); - await filterFxActionTask; - FilterComplete(); + await filterFxActionTask; + FilterComplete(); - //fx.BeginInvoke(_filterParams, _filterResultList, _lastFilterLinesList, _filterHitList, FilterComplete, null); - CheckForFilterDirty(); - } + //fx.BeginInvoke(_filterParams, _filterResultList, _lastFilterLinesList, _filterHitList, FilterComplete, null); + CheckForFilterDirty(); + } - private void MultiThreadedFilter (FilterParams filterParams, List filterResultLines, - List lastFilterLinesList, List filterHitList) - { - ColumnizerCallback callback = new(this); - FilterStarter fs = new(callback, Environment.ProcessorCount + 2); - fs.FilterHitList = _filterHitList; - fs.FilterResultLines = _filterResultList; - fs.LastFilterLinesList = _lastFilterLinesList; - var cancelHandler = new FilterCancelHandler(fs); - OnRegisterCancelHandler(cancelHandler); - long startTime = Environment.TickCount; + private void MultiThreadedFilter (FilterParams filterParams, List filterResultLines, + List lastFilterLinesList, List filterHitList) + { + ColumnizerCallback callback = new(this); + FilterStarter fs = new(callback, Environment.ProcessorCount + 2); + fs.FilterHitList = _filterHitList; + fs.FilterResultLines = _filterResultList; + fs.LastFilterLinesList = _lastFilterLinesList; + var cancelHandler = new FilterCancelHandler(fs); + OnRegisterCancelHandler(cancelHandler); + long startTime = Environment.TickCount; - fs.DoFilter(filterParams, 0, _logFileReader.LineCount, FilterProgressCallback); + fs.DoFilter(filterParams, 0, _logFileReader.LineCount, FilterProgressCallback); - long endTime = Environment.TickCount; + long endTime = Environment.TickCount; - _logger.Debug("Multi threaded filter duration: {0} ms.", endTime - startTime); + _logger.Debug("Multi threaded filter duration: {0} ms.", endTime - startTime); - OnDeRegisterCancelHandler(cancelHandler); - StatusLineText("Filter duration: " + (endTime - startTime) + " ms."); - } + OnDeRegisterCancelHandler(cancelHandler); + StatusLineText("Filter duration: " + (endTime - startTime) + " ms."); + } - private void FilterProgressCallback (int lineCount) - { - UpdateProgressBar(lineCount); - } + private void FilterProgressCallback (int lineCount) + { + UpdateProgressBar(lineCount); + } - private void Filter (FilterParams filterParams, List filterResultLines, List lastFilterLinesList, - List filterHitList) + private void Filter (FilterParams filterParams, List filterResultLines, List lastFilterLinesList, + List filterHitList) + { + long startTime = Environment.TickCount; + try { - long startTime = Environment.TickCount; - try + filterParams.Reset(); + var lineNum = 0; + //AddFilterLineFx addFx = new AddFilterLineFx(AddFilterLine); + ColumnizerCallback callback = new(this); + while (true) { - filterParams.Reset(); - var lineNum = 0; - //AddFilterLineFx addFx = new AddFilterLineFx(AddFilterLine); - ColumnizerCallback callback = new(this); - while (true) + ILogLine line = _logFileReader.GetLogLine(lineNum); + if (line == null) { - ILogLine line = _logFileReader.GetLogLine(lineNum); - if (line == null) - { - break; - } + break; + } - callback.LineNum = lineNum; - if (Util.TestFilterCondition(filterParams, line, callback)) - { - AddFilterLine(lineNum, false, filterParams, filterResultLines, lastFilterLinesList, - filterHitList); - } + callback.LineNum = lineNum; + if (Util.TestFilterCondition(filterParams, line, callback)) + { + AddFilterLine(lineNum, false, filterParams, filterResultLines, lastFilterLinesList, + filterHitList); + } - lineNum++; - if (lineNum % PROGRESS_BAR_MODULO == 0) - { - UpdateProgressBar(lineNum); - } + lineNum++; + if (lineNum % PROGRESS_BAR_MODULO == 0) + { + UpdateProgressBar(lineNum); + } - if (_shouldCancel) - { - break; - } + if (_shouldCancel) + { + break; } } - catch (Exception ex) - { - _logger.Error(ex, "Exception while filtering. Please report to developer: "); - MessageBox.Show(null, - "Exception while filtering. Please report to developer: \n\n" + ex + "\n\n" + ex.StackTrace, - "LogExpert"); - } - - long endTime = Environment.TickCount; - - _logger.Info("Single threaded filter duration: {0} ms.", endTime - startTime); - - StatusLineText("Filter duration: " + (endTime - startTime) + " ms."); } - - /// - /// Returns a list with 'additional filter results'. This is the given line number - /// and (if back spread and/or fore spread is enabled) some additional lines. - /// This function doesn't check the filter condition! - /// - /// - /// - /// - /// - private IList GetAdditionalFilterResults (FilterParams filterParams, int lineNum, IList checkList) + catch (Exception ex) { - IList resultList = []; - //string textLine = this.logFileReader.GetLogLine(lineNum); - //ColumnizerCallback callback = new ColumnizerCallback(this); - //callback.LineNum = lineNum; + _logger.Error(ex, "Exception while filtering. Please report to developer: "); + MessageBox.Show(null, + "Exception while filtering. Please report to developer: \n\n" + ex + "\n\n" + ex.StackTrace, + "LogExpert"); + } - if (filterParams.SpreadBefore == 0 && filterParams.SpreadBehind == 0) - { - resultList.Add(lineNum); - return resultList; - } + long endTime = Environment.TickCount; - // back spread - for (var i = filterParams.SpreadBefore; i > 0; --i) - { - if (lineNum - i > 0) - { - if (!resultList.Contains(lineNum - i) && !checkList.Contains(lineNum - i)) - { - resultList.Add(lineNum - i); - } - } - } + _logger.Info("Single threaded filter duration: {0} ms.", endTime - startTime); - // direct filter hit - if (!resultList.Contains(lineNum) && !checkList.Contains(lineNum)) - { - resultList.Add(lineNum); - } + StatusLineText("Filter duration: " + (endTime - startTime) + " ms."); + } + + /// + /// Returns a list with 'additional filter results'. This is the given line number + /// and (if back spread and/or fore spread is enabled) some additional lines. + /// This function doesn't check the filter condition! + /// + /// + /// + /// + /// + private IList GetAdditionalFilterResults (FilterParams filterParams, int lineNum, IList checkList) + { + IList resultList = []; + //string textLine = this.logFileReader.GetLogLine(lineNum); + //ColumnizerCallback callback = new ColumnizerCallback(this); + //callback.LineNum = lineNum; + + if (filterParams.SpreadBefore == 0 && filterParams.SpreadBehind == 0) + { + resultList.Add(lineNum); + return resultList; + } - // after spread - for (var i = 1; i <= filterParams.SpreadBehind; ++i) + // back spread + for (var i = filterParams.SpreadBefore; i > 0; --i) + { + if (lineNum - i > 0) { - if (lineNum + i < _logFileReader.LineCount) + if (!resultList.Contains(lineNum - i) && !checkList.Contains(lineNum - i)) { - if (!resultList.Contains(lineNum + i) && !checkList.Contains(lineNum + i)) - { - resultList.Add(lineNum + i); - } + resultList.Add(lineNum - i); } } + } - return resultList; + // direct filter hit + if (!resultList.Contains(lineNum) && !checkList.Contains(lineNum)) + { + resultList.Add(lineNum); } - private void AddFilterLine (int lineNum, bool immediate, FilterParams filterParams, List filterResultLines, - List lastFilterLinesList, List filterHitList) + // after spread + for (var i = 1; i <= filterParams.SpreadBehind; ++i) { - int count; - lock (_filterResultList) + if (lineNum + i < _logFileReader.LineCount) { - filterHitList.Add(lineNum); - IList filterResult = GetAdditionalFilterResults(filterParams, lineNum, lastFilterLinesList); - filterResultLines.AddRange(filterResult); - count = filterResultLines.Count; - lastFilterLinesList.AddRange(filterResult); - if (lastFilterLinesList.Count > SPREAD_MAX * 2) + if (!resultList.Contains(lineNum + i) && !checkList.Contains(lineNum + i)) { - lastFilterLinesList.RemoveRange(0, lastFilterLinesList.Count - SPREAD_MAX * 2); + resultList.Add(lineNum + i); } } + } - if (immediate) - { - TriggerFilterLineGuiUpdate(); - } - else if (lineNum % PROGRESS_BAR_MODULO == 0) + return resultList; + } + + private void AddFilterLine (int lineNum, bool immediate, FilterParams filterParams, List filterResultLines, + List lastFilterLinesList, List filterHitList) + { + int count; + lock (_filterResultList) + { + filterHitList.Add(lineNum); + IList filterResult = GetAdditionalFilterResults(filterParams, lineNum, lastFilterLinesList); + filterResultLines.AddRange(filterResult); + count = filterResultLines.Count; + lastFilterLinesList.AddRange(filterResult); + if (lastFilterLinesList.Count > SPREAD_MAX * 2) { - //FunctionWith1IntParam fx = new FunctionWith1IntParam(UpdateFilterCountLabel); - //this.Invoke(fx, new object[] { count}); + lastFilterLinesList.RemoveRange(0, lastFilterLinesList.Count - SPREAD_MAX * 2); } } - private void TriggerFilterLineGuiUpdate () + if (immediate) { - //lock (this.filterUpdateThread) - //{ - // this.filterEventCount++; - // this.filterUpdateEvent.Set(); - //} - Invoke(new MethodInvoker(AddFilterLineGuiUpdate)); + TriggerFilterLineGuiUpdate(); } + else if (lineNum % PROGRESS_BAR_MODULO == 0) + { + //FunctionWith1IntParam fx = new FunctionWith1IntParam(UpdateFilterCountLabel); + //this.Invoke(fx, new object[] { count}); + } + } - //private void FilterUpdateWorker() - //{ - // Thread.CurrentThread.Name = "FilterUpdateWorker"; - // while (true) - // { - // this.filterUpdateEvent.WaitOne(); - // lock (this.filterUpdateThread) - // { - // this.Invoke(new MethodInvoker(AddFilterLineGuiUpdate)); - // this.filterUpdateEvent.Reset(); - // } - - // //_logger.logDebug("FilterUpdateWorker: Waiting for signal"); - // //bool signaled = this.filterUpdateEvent.WaitOne(1000, false); - - // //if (!signaled) - // //{ - // // lock (this.filterUpdateThread) - // // { - // // if (this.filterEventCount > 0) - // // { - // // this.filterEventCount = 0; - // // _logger.logDebug("FilterUpdateWorker: Invoking GUI update because of wait timeout"); - // // this.Invoke(new MethodInvoker(AddFilterLineGuiUpdate)); - // // } - // // } - // //} - // //else - // //{ - // // _logger.logDebug("FilterUpdateWorker: Wakeup signal received."); - // // lock (this.filterUpdateThread) - // // { - // // _logger.logDebug("FilterUpdateWorker: event count: " + this.filterEventCount); - // // if (this.filterEventCount > 100) - // // { - // // this.filterEventCount = 0; - // // _logger.logDebug("FilterUpdateWorker: Invoking GUI update because of event count"); - // // this.Invoke(new MethodInvoker(AddFilterLineGuiUpdate)); - // // } - // // this.filterUpdateEvent.Reset(); - // // } - // //} - // } - //} - - //private void StopFilterUpdateWorkerThread() + private void TriggerFilterLineGuiUpdate () + { + //lock (this.filterUpdateThread) //{ + // this.filterEventCount++; // this.filterUpdateEvent.Set(); - // this.filterUpdateThread.Abort(); - // this.filterUpdateThread.Join(); //} + Invoke(new MethodInvoker(AddFilterLineGuiUpdate)); + } - private void AddFilterLineGuiUpdate () + //private void FilterUpdateWorker() + //{ + // Thread.CurrentThread.Name = "FilterUpdateWorker"; + // while (true) + // { + // this.filterUpdateEvent.WaitOne(); + // lock (this.filterUpdateThread) + // { + // this.Invoke(new MethodInvoker(AddFilterLineGuiUpdate)); + // this.filterUpdateEvent.Reset(); + // } + + // //_logger.logDebug("FilterUpdateWorker: Waiting for signal"); + // //bool signaled = this.filterUpdateEvent.WaitOne(1000, false); + + // //if (!signaled) + // //{ + // // lock (this.filterUpdateThread) + // // { + // // if (this.filterEventCount > 0) + // // { + // // this.filterEventCount = 0; + // // _logger.logDebug("FilterUpdateWorker: Invoking GUI update because of wait timeout"); + // // this.Invoke(new MethodInvoker(AddFilterLineGuiUpdate)); + // // } + // // } + // //} + // //else + // //{ + // // _logger.logDebug("FilterUpdateWorker: Wakeup signal received."); + // // lock (this.filterUpdateThread) + // // { + // // _logger.logDebug("FilterUpdateWorker: event count: " + this.filterEventCount); + // // if (this.filterEventCount > 100) + // // { + // // this.filterEventCount = 0; + // // _logger.logDebug("FilterUpdateWorker: Invoking GUI update because of event count"); + // // this.Invoke(new MethodInvoker(AddFilterLineGuiUpdate)); + // // } + // // this.filterUpdateEvent.Reset(); + // // } + // //} + // } + //} + + //private void StopFilterUpdateWorkerThread() + //{ + // this.filterUpdateEvent.Set(); + // this.filterUpdateThread.Abort(); + // this.filterUpdateThread.Join(); + //} + + private void AddFilterLineGuiUpdate () + { + try { - try + lock (_filterResultList) { - lock (_filterResultList) + lblFilterCount.Text = "" + _filterResultList.Count; + if (filterGridView.RowCount > _filterResultList.Count) { - lblFilterCount.Text = "" + _filterResultList.Count; - if (filterGridView.RowCount > _filterResultList.Count) - { - filterGridView.RowCount = 0; // helps to prevent hang ? - } + filterGridView.RowCount = 0; // helps to prevent hang ? + } - filterGridView.RowCount = _filterResultList.Count; - if (filterGridView.RowCount > 0) - { - filterGridView.FirstDisplayedScrollingRowIndex = filterGridView.RowCount - 1; - } + filterGridView.RowCount = _filterResultList.Count; + if (filterGridView.RowCount > 0) + { + filterGridView.FirstDisplayedScrollingRowIndex = filterGridView.RowCount - 1; + } - if (filterGridView.RowCount == 1) - { - // after a file reload adjusted column sizes anew when the first line arrives - //this.filterGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); - AutoResizeColumns(filterGridView); - } + if (filterGridView.RowCount == 1) + { + // after a file reload adjusted column sizes anew when the first line arrives + //this.filterGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); + AutoResizeColumns(filterGridView); } } - catch (Exception e) - { - _logger.Error(e, "AddFilterLineGuiUpdate(): "); - } } - - private void UpdateProgressBar (int value) + catch (Exception e) { - _progressEventArgs.Value = value; - if (value > _progressEventArgs.MaxValue) - { - // can occur if new lines will be added while filtering - _progressEventArgs.MaxValue = value; - } - - SendProgressBarUpdate(); + _logger.Error(e, "AddFilterLineGuiUpdate(): "); } + } - private void FilterComplete () + private void UpdateProgressBar (int value) + { + _progressEventArgs.Value = value; + if (value > _progressEventArgs.MaxValue) { - if (!IsDisposed && !_waitingForClose && !Disposing) - { - Invoke(new MethodInvoker(ResetStatusAfterFilter)); - } + // can occur if new lines will be added while filtering + _progressEventArgs.MaxValue = value; } - private void FilterComplete (IAsyncResult result) + SendProgressBarUpdate(); + } + + private void FilterComplete () + { + if (!IsDisposed && !_waitingForClose && !Disposing) { - if (!IsDisposed && !_waitingForClose && !Disposing) - { - Invoke(new MethodInvoker(ResetStatusAfterFilter)); - } + Invoke(new MethodInvoker(ResetStatusAfterFilter)); } + } - private void ResetStatusAfterFilter () + private void FilterComplete (IAsyncResult result) + { + if (!IsDisposed && !_waitingForClose && !Disposing) { - try - { - //StatusLineText(""); - _isSearching = false; - _progressEventArgs.Value = _progressEventArgs.MaxValue; - _progressEventArgs.Visible = false; - SendProgressBarUpdate(); - filterGridView.RowCount = _filterResultList.Count; - //this.filterGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); - AutoResizeColumns(filterGridView); - lblFilterCount.Text = "" + _filterResultList.Count; - if (filterGridView.RowCount > 0) - { - filterGridView.Focus(); - } - - filterSearchButton.Enabled = true; - } - catch (NullReferenceException e) - { - // See https://connect.microsoft.com/VisualStudio/feedback/details/366943/autoresizecolumns-in-datagridview-throws-nullreferenceexception - // There are some rare situations with null ref exceptions when resizing columns and on filter finished - // So catch them here. Better than crashing. - _logger.Error(e, "Error: "); - } + Invoke(new MethodInvoker(ResetStatusAfterFilter)); } + } - private void ClearFilterList () + private void ResetStatusAfterFilter () + { + try { - try + //StatusLineText(""); + _isSearching = false; + _progressEventArgs.Value = _progressEventArgs.MaxValue; + _progressEventArgs.Visible = false; + SendProgressBarUpdate(); + filterGridView.RowCount = _filterResultList.Count; + //this.filterGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); + AutoResizeColumns(filterGridView); + lblFilterCount.Text = "" + _filterResultList.Count; + if (filterGridView.RowCount > 0) { - //this.shouldCancel = true; - lock (_filterResultList) - { - filterGridView.SuspendLayout(); - filterGridView.RowCount = 0; - lblFilterCount.Text = "0"; - _filterResultList = []; - _lastFilterLinesList = []; - _filterHitList = []; - //this.filterGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); - filterGridView.ResumeLayout(); - } + filterGridView.Focus(); } - catch (Exception ex) - { - _logger.Error(ex, "Wieder dieser sporadische Fehler: "); - MessageBox.Show(null, ex.StackTrace, "Wieder dieser sporadische Fehler:"); - } + filterSearchButton.Enabled = true; } - - private void ClearBookmarkList () + catch (NullReferenceException e) { - _bookmarkProvider.ClearAllBookmarks(); + // See https://connect.microsoft.com/VisualStudio/feedback/details/366943/autoresizecolumns-in-datagridview-throws-nullreferenceexception + // There are some rare situations with null ref exceptions when resizing columns and on filter finished + // So catch them here. Better than crashing. + _logger.Error(e, "Error: "); } + } - /** - * Shift filter list line entries after a logfile rollover - */ - - private void ShiftFilterLines (int offset) + private void ClearFilterList () + { + try { - List newFilterList = []; + //this.shouldCancel = true; lock (_filterResultList) { - foreach (var lineNum in _filterResultList) - { - var line = lineNum - offset; - if (line >= 0) - { - newFilterList.Add(line); - } - } - - _filterResultList = newFilterList; + filterGridView.SuspendLayout(); + filterGridView.RowCount = 0; + lblFilterCount.Text = "0"; + _filterResultList = []; + _lastFilterLinesList = []; + _filterHitList = []; + //this.filterGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); + filterGridView.ResumeLayout(); } + } + catch (Exception ex) + { + _logger.Error(ex, "Wieder dieser sporadische Fehler: "); + + MessageBox.Show(null, ex.StackTrace, "Wieder dieser sporadische Fehler:"); + } + } - newFilterList = []; - foreach (var lineNum in _filterHitList) + private void ClearBookmarkList () + { + _bookmarkProvider.ClearAllBookmarks(); + } + + /** + * Shift filter list line entries after a logfile rollover + */ + + private void ShiftFilterLines (int offset) + { + List newFilterList = []; + lock (_filterResultList) + { + foreach (var lineNum in _filterResultList) { var line = lineNum - offset; if (line >= 0) @@ -2422,1318 +2409,1330 @@ private void ShiftFilterLines (int offset) } } - _filterHitList = newFilterList; - - var count = SPREAD_MAX; - if (_filterResultList.Count < SPREAD_MAX) - { - count = _filterResultList.Count; - } - - _lastFilterLinesList = _filterResultList.GetRange(_filterResultList.Count - count, count); - - //this.filterGridView.RowCount = this.filterResultList.Count; - //this.filterCountLabel.Text = "" + this.filterResultList.Count; - //this.BeginInvoke(new MethodInvoker(this.filterGridView.Refresh)); - //this.BeginInvoke(new MethodInvoker(AddFilterLineGuiUpdate)); - TriggerFilterLineGuiUpdate(); + _filterResultList = newFilterList; } - private void CheckForFilterDirty () + newFilterList = []; + foreach (var lineNum in _filterHitList) { - if (IsFilterSearchDirty(_filterParams)) - { - filterSearchButton.Image = _searchButtonImage; - saveFilterButton.Enabled = false; - } - else + var line = lineNum - offset; + if (line >= 0) { - filterSearchButton.Image = null; - saveFilterButton.Enabled = true; + newFilterList.Add(line); } } - private bool IsFilterSearchDirty (FilterParams filterParams) + _filterHitList = newFilterList; + + var count = SPREAD_MAX; + if (_filterResultList.Count < SPREAD_MAX) { - if (!filterParams.SearchText.Equals(filterComboBox.Text)) - { - return true; - } + count = _filterResultList.Count; + } - if (filterParams.IsRangeSearch != rangeCheckBox.Checked) - { - return true; - } + _lastFilterLinesList = _filterResultList.GetRange(_filterResultList.Count - count, count); - if (filterParams.IsRangeSearch && !filterParams.RangeSearchText.Equals(filterRangeComboBox.Text)) - { - return true; - } + //this.filterGridView.RowCount = this.filterResultList.Count; + //this.filterCountLabel.Text = "" + this.filterResultList.Count; + //this.BeginInvoke(new MethodInvoker(this.filterGridView.Refresh)); + //this.BeginInvoke(new MethodInvoker(AddFilterLineGuiUpdate)); + TriggerFilterLineGuiUpdate(); + } - if (filterParams.IsRegex != filterRegexCheckBox.Checked) - { - return true; - } + private void CheckForFilterDirty () + { + if (IsFilterSearchDirty(_filterParams)) + { + filterSearchButton.Image = _searchButtonImage; + saveFilterButton.Enabled = false; + } + else + { + filterSearchButton.Image = null; + saveFilterButton.Enabled = true; + } + } - if (filterParams.IsInvert != invertFilterCheckBox.Checked) - { - return true; - } + private bool IsFilterSearchDirty (FilterParams filterParams) + { + if (!filterParams.SearchText.Equals(filterComboBox.Text)) + { + return true; + } - if (filterParams.SpreadBefore != filterKnobBackSpread.Value) - { - return true; - } + if (filterParams.IsRangeSearch != rangeCheckBox.Checked) + { + return true; + } - if (filterParams.SpreadBehind != filterKnobForeSpread.Value) - { - return true; - } + if (filterParams.IsRangeSearch && !filterParams.RangeSearchText.Equals(filterRangeComboBox.Text)) + { + return true; + } - if (filterParams.FuzzyValue != fuzzyKnobControl.Value) - { - return true; - } + if (filterParams.IsRegex != filterRegexCheckBox.Checked) + { + return true; + } - if (filterParams.ColumnRestrict != columnRestrictCheckBox.Checked) - { - return true; - } + if (filterParams.IsInvert != invertFilterCheckBox.Checked) + { + return true; + } - if (filterParams.IsCaseSensitive != filterCaseSensitiveCheckBox.Checked) - { - return true; - } + if (filterParams.SpreadBefore != filterKnobBackSpread.Value) + { + return true; + } - return false; + if (filterParams.SpreadBehind != filterKnobForeSpread.Value) + { + return true; } - private void AdjustMinimumGridWith () + if (filterParams.FuzzyValue != fuzzyKnobControl.Value) { - if (dataGridView.Columns.Count > 1) - { - //this.dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); - AutoResizeColumns(dataGridView); + return true; + } - var width = dataGridView.Columns.GetColumnsWidth(DataGridViewElementStates.Visible); - var diff = dataGridView.Width - width; - if (diff > 0) - { - diff -= dataGridView.RowHeadersWidth / 2; - dataGridView.Columns[dataGridView.Columns.GetColumnCount(DataGridViewElementStates.None) - 1].Width += diff; - filterGridView.Columns[filterGridView.Columns.GetColumnCount(DataGridViewElementStates.None) - 1].Width += diff; - } - } + if (filterParams.ColumnRestrict != columnRestrictCheckBox.Checked) + { + return true; + } + + if (filterParams.IsCaseSensitive != filterCaseSensitiveCheckBox.Checked) + { + return true; } - private void InvalidateCurrentRow (BufferedDataGridView gridView) + return false; + } + + private void AdjustMinimumGridWith () + { + if (dataGridView.Columns.Count > 1) { - if (gridView.CurrentCellAddress.Y > -1) + //this.dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); + AutoResizeColumns(dataGridView); + + var width = dataGridView.Columns.GetColumnsWidth(DataGridViewElementStates.Visible); + var diff = dataGridView.Width - width; + if (diff > 0) { - gridView.InvalidateRow(gridView.CurrentCellAddress.Y); + diff -= dataGridView.RowHeadersWidth / 2; + dataGridView.Columns[dataGridView.Columns.GetColumnCount(DataGridViewElementStates.None) - 1].Width += diff; + filterGridView.Columns[filterGridView.Columns.GetColumnCount(DataGridViewElementStates.None) - 1].Width += diff; } } + } - private void InvalidateCurrentRow () + private void InvalidateCurrentRow (BufferedDataGridView gridView) + { + if (gridView.CurrentCellAddress.Y > -1) { - InvalidateCurrentRow(dataGridView); - InvalidateCurrentRow(filterGridView); + gridView.InvalidateRow(gridView.CurrentCellAddress.Y); } + } - private void DisplayCurrentFileOnStatusline () + private void InvalidateCurrentRow () + { + InvalidateCurrentRow(dataGridView); + InvalidateCurrentRow(filterGridView); + } + + private void DisplayCurrentFileOnStatusline () + { + if (_logFileReader.IsMultiFile) { - if (_logFileReader.IsMultiFile) + try { - try + if (dataGridView.CurrentRow != null && dataGridView.CurrentRow.Index > -1) { - if (dataGridView.CurrentRow != null && dataGridView.CurrentRow.Index > -1) + var fileName = _logFileReader.GetLogFileNameForLine(dataGridView.CurrentRow.Index); + if (fileName != null) { - var fileName = _logFileReader.GetLogFileNameForLine(dataGridView.CurrentRow.Index); - if (fileName != null) - { - StatusLineText(Util.GetNameFromPath(fileName)); - } + StatusLineText(Util.GetNameFromPath(fileName)); } } - catch (Exception) - { - // TODO: handle this concurrent situation better: - // this.dataGridView.CurrentRow may be null even if checked before. - // This can happen when MultiFile shift deselects the current row because there - // are less lines after rollover than before. - // access to dataGridView-Rows should be locked - } } - } - - private void UpdateSelectionDisplay () - { - if (_noSelectionUpdates) + catch (Exception) { - return; + // TODO: handle this concurrent situation better: + // this.dataGridView.CurrentRow may be null even if checked before. + // This can happen when MultiFile shift deselects the current row because there + // are less lines after rollover than before. + // access to dataGridView-Rows should be locked } } + } - private void UpdateFilterHistoryFromSettings () + private void UpdateSelectionDisplay () + { + if (_noSelectionUpdates) { - ConfigManager.Settings.filterHistoryList = ConfigManager.Settings.filterHistoryList; - filterComboBox.Items.Clear(); - foreach (var item in ConfigManager.Settings.filterHistoryList) - { - filterComboBox.Items.Add(item); - } - - filterRangeComboBox.Items.Clear(); - foreach (var item in ConfigManager.Settings.filterRangeHistoryList) - { - filterRangeComboBox.Items.Add(item); - } + return; } + } - private void StatusLineText (string text) + private void UpdateFilterHistoryFromSettings () + { + ConfigManager.Settings.filterHistoryList = ConfigManager.Settings.filterHistoryList; + filterComboBox.Items.Clear(); + foreach (var item in ConfigManager.Settings.filterHistoryList) { - _statusEventArgs.StatusText = text; - SendStatusLineUpdate(); + filterComboBox.Items.Add(item); } - private void StatusLineError (string text) + filterRangeComboBox.Items.Clear(); + foreach (var item in ConfigManager.Settings.filterRangeHistoryList) { - StatusLineText(text); - _isErrorShowing = true; + filterRangeComboBox.Items.Add(item); } + } + + private void StatusLineText (string text) + { + _statusEventArgs.StatusText = text; + SendStatusLineUpdate(); + } + + private void StatusLineError (string text) + { + StatusLineText(text); + _isErrorShowing = true; + } + + private void RemoveStatusLineError () + { + StatusLineText(""); + _isErrorShowing = false; + } + + private void SendGuiStateUpdate () + { + OnGuiState(_guiStateArgs); + } - private void RemoveStatusLineError () + private void SendProgressBarUpdate () + { + OnProgressBarUpdate(_progressEventArgs); + } + + private void SendStatusLineUpdate () + { + OnStatusLine(_statusEventArgs); + } + + private void ShowAdvancedFilterPanel (bool show) + { + if (show) { - StatusLineText(""); - _isErrorShowing = false; + advancedButton.Text = "Hide advanced..."; + advancedButton.Image = null; } - - private void SendGuiStateUpdate () + else { - OnGuiState(_guiStateArgs); + advancedButton.Text = "Show advanced..."; + CheckForAdvancedButtonDirty(); } - private void SendProgressBarUpdate () + advancedFilterSplitContainer.Panel1Collapsed = !show; + advancedFilterSplitContainer.SplitterDistance = FILTER_ADVANCED_SPLITTER_DISTANCE; + _showAdvanced = show; + } + + private void CheckForAdvancedButtonDirty () + { + if (IsAdvancedOptionActive() && !_showAdvanced) { - OnProgressBarUpdate(_progressEventArgs); + advancedButton.Image = _advancedButtonImage; } - - private void SendStatusLineUpdate () + else { - OnStatusLine(_statusEventArgs); + advancedButton.Image = null; } + } + + private void FilterToTab () + { + filterSearchButton.Enabled = false; + Task.Run(() => WriteFilterToTab()); + } - private void ShowAdvancedFilterPanel (bool show) + private void WriteFilterToTab () + { + FilterPipe pipe = new(_filterParams.Clone(), this); + lock (_filterResultList) { - if (show) + var namePrefix = "->F"; + string title; + if (IsTempFile) { - advancedButton.Text = "Hide advanced..."; - advancedButton.Image = null; + title = TempTitleName + namePrefix + ++_filterPipeNameCounter; } else { - advancedButton.Text = "Show advanced..."; - CheckForAdvancedButtonDirty(); + title = Util.GetNameFromPath(FileName) + namePrefix + ++_filterPipeNameCounter; } - advancedFilterSplitContainer.Panel1Collapsed = !show; - advancedFilterSplitContainer.SplitterDistance = FILTER_ADVANCED_SPLITTER_DISTANCE; - _showAdvanced = show; + WritePipeToTab(pipe, _filterResultList, title, null); } + } - private void CheckForAdvancedButtonDirty () - { - if (IsAdvancedOptionActive() && !_showAdvanced) - { - advancedButton.Image = _advancedButtonImage; - } - else - { - advancedButton.Image = null; - } - } + private void WritePipeToTab (FilterPipe pipe, IList lineNumberList, string name, PersistenceData persistenceData) + { + _logger.Info("WritePipeToTab(): {0} lines.", lineNumberList.Count); + StatusLineText("Writing to temp file... Press ESC to cancel."); + _guiStateArgs.MenuEnabled = false; + SendGuiStateUpdate(); + _progressEventArgs.MinValue = 0; + _progressEventArgs.MaxValue = lineNumberList.Count; + _progressEventArgs.Value = 0; + _progressEventArgs.Visible = true; + Invoke(new MethodInvoker(SendProgressBarUpdate)); + _isSearching = true; + _shouldCancel = false; - private void FilterToTab () + lock (_filterPipeList) { - filterSearchButton.Enabled = false; - Task.Run(() => WriteFilterToTab()); + _filterPipeList.Add(pipe); } - private void WriteFilterToTab () + pipe.Closed += OnPipeDisconnected; + var count = 0; + pipe.OpenFile(); + LogExpertCallback callback = new(this); + foreach (var i in lineNumberList) { - FilterPipe pipe = new(_filterParams.Clone(), this); - lock (_filterResultList) + if (_shouldCancel) { - var namePrefix = "->F"; - string title; - if (IsTempFile) - { - title = TempTitleName + namePrefix + ++_filterPipeNameCounter; - } - else - { - title = Util.GetNameFromPath(FileName) + namePrefix + ++_filterPipeNameCounter; - } - - WritePipeToTab(pipe, _filterResultList, title, null); + break; } - } - - private void WritePipeToTab (FilterPipe pipe, IList lineNumberList, string name, PersistenceData persistenceData) - { - _logger.Info("WritePipeToTab(): {0} lines.", lineNumberList.Count); - StatusLineText("Writing to temp file... Press ESC to cancel."); - _guiStateArgs.MenuEnabled = false; - SendGuiStateUpdate(); - _progressEventArgs.MinValue = 0; - _progressEventArgs.MaxValue = lineNumberList.Count; - _progressEventArgs.Value = 0; - _progressEventArgs.Visible = true; - Invoke(new MethodInvoker(SendProgressBarUpdate)); - _isSearching = true; - _shouldCancel = false; - lock (_filterPipeList) + ILogLine line = _logFileReader.GetLogLine(i); + if (CurrentColumnizer is ILogLineXmlColumnizer) { - _filterPipeList.Add(pipe); + callback.LineNum = i; + line = (CurrentColumnizer as ILogLineXmlColumnizer).GetLineTextForClipboard(line, callback); } - pipe.Closed += OnPipeDisconnected; - var count = 0; - pipe.OpenFile(); - LogExpertCallback callback = new(this); - foreach (var i in lineNumberList) + pipe.WriteToPipe(line, i); + if (++count % PROGRESS_BAR_MODULO == 0) { - if (_shouldCancel) - { - break; - } - - ILogLine line = _logFileReader.GetLogLine(i); - if (CurrentColumnizer is ILogLineXmlColumnizer) - { - callback.LineNum = i; - line = (CurrentColumnizer as ILogLineXmlColumnizer).GetLineTextForClipboard(line, callback); - } - - pipe.WriteToPipe(line, i); - if (++count % PROGRESS_BAR_MODULO == 0) - { - _progressEventArgs.Value = count; - Invoke(new MethodInvoker(SendProgressBarUpdate)); - } + _progressEventArgs.Value = count; + Invoke(new MethodInvoker(SendProgressBarUpdate)); } - - pipe.CloseFile(); - _logger.Info("WritePipeToTab(): finished"); - Invoke(new WriteFilterToTabFinishedFx(WriteFilterToTabFinished), pipe, name, persistenceData); } - private void WriteFilterToTabFinished (FilterPipe pipe, string name, PersistenceData persistenceData) + pipe.CloseFile(); + _logger.Info("WritePipeToTab(): finished"); + Invoke(new WriteFilterToTabFinishedFx(WriteFilterToTabFinished), pipe, name, persistenceData); + } + + private void WriteFilterToTabFinished (FilterPipe pipe, string name, PersistenceData persistenceData) + { + _isSearching = false; + if (!_shouldCancel) { - _isSearching = false; - if (!_shouldCancel) + var title = name; + ILogLineColumnizer preProcessColumnizer = null; + if (CurrentColumnizer is not ILogLineXmlColumnizer) { - var title = name; - ILogLineColumnizer preProcessColumnizer = null; - if (CurrentColumnizer is not ILogLineXmlColumnizer) - { - preProcessColumnizer = CurrentColumnizer; - } - - LogWindow newWin = _parentLogTabWin.AddFilterTab(pipe, title, preProcessColumnizer); - newWin.FilterPipe = pipe; - pipe.OwnLogWindow = newWin; - if (persistenceData != null) - { - Task.Run(() => FilterRestore(newWin, persistenceData)); - } + preProcessColumnizer = CurrentColumnizer; } - _progressEventArgs.Value = _progressEventArgs.MaxValue; - _progressEventArgs.Visible = false; - SendProgressBarUpdate(); - _guiStateArgs.MenuEnabled = true; - SendGuiStateUpdate(); - StatusLineText(""); - filterSearchButton.Enabled = true; - } - - /// - /// Used to create a new tab and pipe the given content into it. - /// - /// - /// - internal void WritePipeTab (IList lineEntryList, string title) - { - FilterPipe pipe = new(new FilterParams(), this); - pipe.IsStopped = true; - pipe.Closed += OnPipeDisconnected; - pipe.OpenFile(); - foreach (LineEntry entry in lineEntryList) + LogWindow newWin = _parentLogTabWin.AddFilterTab(pipe, title, preProcessColumnizer); + newWin.FilterPipe = pipe; + pipe.OwnLogWindow = newWin; + if (persistenceData != null) { - pipe.WriteToPipe(entry.logLine, entry.lineNum); + Task.Run(() => FilterRestore(newWin, persistenceData)); } - - pipe.CloseFile(); - Invoke(new WriteFilterToTabFinishedFx(WriteFilterToTabFinished), [pipe, title, null]); } - private void FilterRestore (LogWindow newWin, PersistenceData persistenceData) + _progressEventArgs.Value = _progressEventArgs.MaxValue; + _progressEventArgs.Visible = false; + SendProgressBarUpdate(); + _guiStateArgs.MenuEnabled = true; + SendGuiStateUpdate(); + StatusLineText(""); + filterSearchButton.Enabled = true; + } + + /// + /// Used to create a new tab and pipe the given content into it. + /// + /// + /// + internal void WritePipeTab (IList lineEntryList, string title) + { + FilterPipe pipe = new(new FilterParams(), this); + pipe.IsStopped = true; + pipe.Closed += OnPipeDisconnected; + pipe.OpenFile(); + foreach (LineEntry entry in lineEntryList) { - newWin.WaitForLoadingFinished(); - ILogLineColumnizer columnizer = ColumnizerPicker.FindColumnizerByName(persistenceData.columnizerName, - PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers); - if (columnizer != null) - { - SetColumnizerFx fx = newWin.ForceColumnizer; - newWin.Invoke(fx, [columnizer]); - } - else - { - _logger.Warn("FilterRestore(): Columnizer {0} not found", persistenceData.columnizerName); - } + pipe.WriteToPipe(entry.logLine, entry.lineNum); + } + + pipe.CloseFile(); + Invoke(new WriteFilterToTabFinishedFx(WriteFilterToTabFinished), [pipe, title, null]); + } - newWin.BeginInvoke(new RestoreFiltersFx(newWin.RestoreFilters), [persistenceData]); + private void FilterRestore (LogWindow newWin, PersistenceData persistenceData) + { + newWin.WaitForLoadingFinished(); + ILogLineColumnizer columnizer = ColumnizerPicker.FindColumnizerByName(persistenceData.columnizerName, + PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers); + if (columnizer != null) + { + SetColumnizerFx fx = newWin.ForceColumnizer; + newWin.Invoke(fx, [columnizer]); + } + else + { + _logger.Warn("FilterRestore(): Columnizer {0} not found", persistenceData.columnizerName); } - private void ProcessFilterPipes (int lineNum) + newWin.BeginInvoke(new RestoreFiltersFx(newWin.RestoreFilters), [persistenceData]); + } + + private void ProcessFilterPipes (int lineNum) + { + ILogLine searchLine = _logFileReader.GetLogLine(lineNum); + if (searchLine == null) { - ILogLine searchLine = _logFileReader.GetLogLine(lineNum); - if (searchLine == null) - { - return; - } + return; + } - ColumnizerCallback callback = new(this); - callback.LineNum = lineNum; - IList deleteList = []; - lock (_filterPipeList) + ColumnizerCallback callback = new(this); + callback.LineNum = lineNum; + IList deleteList = []; + lock (_filterPipeList) + { + foreach (FilterPipe pipe in _filterPipeList) { - foreach (FilterPipe pipe in _filterPipeList) + if (pipe.IsStopped) { - if (pipe.IsStopped) - { - continue; - } + continue; + } - long startTime = Environment.TickCount; - if (Util.TestFilterCondition(pipe.FilterParams, searchLine, callback)) + long startTime = Environment.TickCount; + if (Util.TestFilterCondition(pipe.FilterParams, searchLine, callback)) + { + IList filterResult = + GetAdditionalFilterResults(pipe.FilterParams, lineNum, pipe.LastLinesHistoryList); + pipe.OpenFile(); + foreach (var line in filterResult) { - IList filterResult = - GetAdditionalFilterResults(pipe.FilterParams, lineNum, pipe.LastLinesHistoryList); - pipe.OpenFile(); - foreach (var line in filterResult) + pipe.LastLinesHistoryList.Add(line); + if (pipe.LastLinesHistoryList.Count > SPREAD_MAX * 2) { - pipe.LastLinesHistoryList.Add(line); - if (pipe.LastLinesHistoryList.Count > SPREAD_MAX * 2) - { - pipe.LastLinesHistoryList.RemoveAt(0); - } - - ILogLine textLine = _logFileReader.GetLogLine(line); - var fileOk = pipe.WriteToPipe(textLine, line); - if (!fileOk) - { - deleteList.Add(pipe); - } + pipe.LastLinesHistoryList.RemoveAt(0); } - pipe.CloseFile(); + ILogLine textLine = _logFileReader.GetLogLine(line); + var fileOk = pipe.WriteToPipe(textLine, line); + if (!fileOk) + { + deleteList.Add(pipe); + } } - long endTime = Environment.TickCount; - //_logger.logDebug("ProcessFilterPipes(" + lineNum + ") duration: " + ((endTime - startTime))); + pipe.CloseFile(); } - } - foreach (FilterPipe pipe in deleteList) - { - _filterPipeList.Remove(pipe); + long endTime = Environment.TickCount; + //_logger.logDebug("ProcessFilterPipes(" + lineNum + ") duration: " + ((endTime - startTime))); } } - private void CopyMarkedLinesToClipboard () + foreach (FilterPipe pipe in deleteList) { - if (_guiStateArgs.CellSelectMode) - { - DataObject data = dataGridView.GetClipboardContent(); - Clipboard.SetDataObject(data); - } - else + _filterPipeList.Remove(pipe); + } + } + + private void CopyMarkedLinesToClipboard () + { + if (_guiStateArgs.CellSelectMode) + { + DataObject data = dataGridView.GetClipboardContent(); + Clipboard.SetDataObject(data); + } + else + { + List lineNumList = []; + foreach (DataGridViewRow row in dataGridView.SelectedRows) { - List lineNumList = []; - foreach (DataGridViewRow row in dataGridView.SelectedRows) + if (row.Index != -1) { - if (row.Index != -1) - { - lineNumList.Add(row.Index); - } + lineNumList.Add(row.Index); } + } - lineNumList.Sort(); - StringBuilder clipText = new(); - LogExpertCallback callback = new(this); + lineNumList.Sort(); + StringBuilder clipText = new(); + LogExpertCallback callback = new(this); - var xmlColumnizer = _currentColumnizer as ILogLineXmlColumnizer; + var xmlColumnizer = _currentColumnizer as ILogLineXmlColumnizer; - foreach (var lineNum in lineNumList) + foreach (var lineNum in lineNumList) + { + ILogLine line = _logFileReader.GetLogLine(lineNum); + if (xmlColumnizer != null) { - ILogLine line = _logFileReader.GetLogLine(lineNum); - if (xmlColumnizer != null) - { - callback.LineNum = lineNum; - line = xmlColumnizer.GetLineTextForClipboard(line, callback); - } - - clipText.AppendLine(line.ToClipBoardText()); + callback.LineNum = lineNum; + line = xmlColumnizer.GetLineTextForClipboard(line, callback); } - Clipboard.SetText(clipText.ToString()); + clipText.AppendLine(line.ToClipBoardText()); } - } - /// - /// Set an Encoding which shall be used when loading a file. Used before a file is loaded. - /// - /// - private void SetExplicitEncoding (Encoding encoding) - { - EncodingOptions.Encoding = encoding; + Clipboard.SetText(clipText.ToString()); } + } + + /// + /// Set an Encoding which shall be used when loading a file. Used before a file is loaded. + /// + /// + private void SetExplicitEncoding (Encoding encoding) + { + EncodingOptions.Encoding = encoding; + } - private void ApplyDataGridViewPrefs (BufferedDataGridView dataGridView, Preferences prefs) + private void ApplyDataGridViewPrefs (BufferedDataGridView dataGridView, Preferences prefs) + { + if (dataGridView.Columns.GetColumnCount(DataGridViewElementStates.None) > 1) { - if (dataGridView.Columns.GetColumnCount(DataGridViewElementStates.None) > 1) + if (prefs.setLastColumnWidth) { - if (prefs.setLastColumnWidth) - { - dataGridView.Columns[dataGridView.Columns.GetColumnCount(DataGridViewElementStates.None) - 1].MinimumWidth = prefs.lastColumnWidth; - } - else - { - // Workaround for a .NET bug which brings the DataGridView into an unstable state (causing lots of NullReferenceExceptions). - dataGridView.FirstDisplayedScrollingColumnIndex = 0; - - dataGridView.Columns[dataGridView.Columns.GetColumnCount(DataGridViewElementStates.None) - 1].MinimumWidth = 5; // default - } + dataGridView.Columns[dataGridView.Columns.GetColumnCount(DataGridViewElementStates.None) - 1].MinimumWidth = prefs.lastColumnWidth; } - - if (dataGridView.RowCount > 0) + else { - dataGridView.UpdateRowHeightInfo(0, true); + // Workaround for a .NET bug which brings the DataGridView into an unstable state (causing lots of NullReferenceExceptions). + dataGridView.FirstDisplayedScrollingColumnIndex = 0; + + dataGridView.Columns[dataGridView.Columns.GetColumnCount(DataGridViewElementStates.None) - 1].MinimumWidth = 5; // default } + } - dataGridView.Invalidate(); - dataGridView.Refresh(); - AutoResizeColumns(dataGridView); + if (dataGridView.RowCount > 0) + { + dataGridView.UpdateRowHeightInfo(0, true); } - private IList GetSelectedContent () + dataGridView.Invalidate(); + dataGridView.Refresh(); + AutoResizeColumns(dataGridView); + } + + private IList GetSelectedContent () + { + if (dataGridView.SelectionMode == DataGridViewSelectionMode.FullRowSelect) { - if (dataGridView.SelectionMode == DataGridViewSelectionMode.FullRowSelect) - { - List lineNumList = []; + List lineNumList = []; - foreach (DataGridViewRow row in dataGridView.SelectedRows) + foreach (DataGridViewRow row in dataGridView.SelectedRows) + { + if (row.Index != -1) { - if (row.Index != -1) - { - lineNumList.Add(row.Index); - } + lineNumList.Add(row.Index); } - - lineNumList.Sort(); - return lineNumList; } - return []; + lineNumList.Sort(); + return lineNumList; } - /* ======================================================================== - * Timestamp stuff - * =======================================================================*/ - - private void SetTimestampLimits () - { - if (!CurrentColumnizer.IsTimeshiftImplemented()) - { - return; - } + return []; + } - var line = 0; - _guiStateArgs.MinTimestamp = GetTimestampForLineForward(ref line, true); - line = dataGridView.RowCount - 1; - _guiStateArgs.MaxTimestamp = GetTimestampForLine(ref line, true); - SendGuiStateUpdate(); - } + /* ======================================================================== + * Timestamp stuff + * =======================================================================*/ - private void AdjustHighlightSplitterWidth () + private void SetTimestampLimits () + { + if (!CurrentColumnizer.IsTimeshiftImplemented()) { - //int size = this.editHighlightsSplitContainer.Panel2Collapsed ? 600 : 660; - //int distance = this.highlightSplitContainer.Width - size; - //if (distance < 10) - // distance = 10; - //this.highlightSplitContainer.SplitterDistance = distance; + return; } - private void BookmarkComment (Bookmark bookmark) + var line = 0; + _guiStateArgs.MinTimestamp = GetTimestampForLineForward(ref line, true); + line = dataGridView.RowCount - 1; + _guiStateArgs.MaxTimestamp = GetTimestampForLine(ref line, true); + SendGuiStateUpdate(); + } + + private void AdjustHighlightSplitterWidth () + { + //int size = this.editHighlightsSplitContainer.Panel2Collapsed ? 600 : 660; + //int distance = this.highlightSplitContainer.Width - size; + //if (distance < 10) + // distance = 10; + //this.highlightSplitContainer.SplitterDistance = distance; + } + + private void BookmarkComment (Bookmark bookmark) + { + BookmarkCommentDlg dlg = new(); + dlg.Comment = bookmark.Text; + if (dlg.ShowDialog() == DialogResult.OK) { - BookmarkCommentDlg dlg = new(); - dlg.Comment = bookmark.Text; - if (dlg.ShowDialog() == DialogResult.OK) - { - bookmark.Text = dlg.Comment; - dataGridView.Refresh(); - OnBookmarkTextChanged(bookmark); - } + bookmark.Text = dlg.Comment; + dataGridView.Refresh(); + OnBookmarkTextChanged(bookmark); } + } - /// - /// Indicates which columns we are filtering on - /// - /// - /// - private string CalculateColumnNames (FilterParams filter) - { - var names = string.Empty; + /// + /// Indicates which columns we are filtering on + /// + /// + /// + private string CalculateColumnNames (FilterParams filter) + { + var names = string.Empty; - if (filter.ColumnRestrict) + if (filter.ColumnRestrict) + { + foreach (var colIndex in filter.ColumnList) { - foreach (var colIndex in filter.ColumnList) + if (colIndex < dataGridView.Columns.GetColumnCount(DataGridViewElementStates.None) - 2) { - if (colIndex < dataGridView.Columns.GetColumnCount(DataGridViewElementStates.None) - 2) + if (names.Length > 0) { - if (names.Length > 0) - { - names += ", "; - } - - names += dataGridView.Columns[2 + colIndex] - .HeaderText; // skip first two columns: marker + line number + names += ", "; } + + names += dataGridView.Columns[2 + colIndex] + .HeaderText; // skip first two columns: marker + line number } } - - return names; } - private void ApplyFrozenState (BufferedDataGridView gridView) - { - SortedDictionary dict = []; - foreach (DataGridViewColumn col in gridView.Columns) - { - dict.Add(col.DisplayIndex, col); - } + return names; + } - foreach (DataGridViewColumn col in dict.Values) - { - col.Frozen = _freezeStateMap.ContainsKey(gridView) && _freezeStateMap[gridView]; - var sel = col.HeaderCell.Selected; - if (col.Index == _selectedCol) - { - break; - } - } + private void ApplyFrozenState (BufferedDataGridView gridView) + { + SortedDictionary dict = []; + foreach (DataGridViewColumn col in gridView.Columns) + { + dict.Add(col.DisplayIndex, col); } - private void ShowTimeSpread (bool show) + foreach (DataGridViewColumn col in dict.Values) { - if (show) - { - tableLayoutPanel1.ColumnStyles[1].Width = 16; - } - else + col.Frozen = _freezeStateMap.ContainsKey(gridView) && _freezeStateMap[gridView]; + var sel = col.HeaderCell.Selected; + if (col.Index == _selectedCol) { - tableLayoutPanel1.ColumnStyles[1].Width = 0; + break; } - - _timeSpreadCalc.Enabled = show; } + } - protected internal void AddTempFileTab (string fileName, string title) + private void ShowTimeSpread (bool show) + { + if (show) { - _parentLogTabWin.AddTempFileTab(fileName, title); + tableLayoutPanel1.ColumnStyles[1].Width = 16; } - - private void InitPatternWindow () + else { - //PatternStatistic(this.patternArgs); - _patternWindow = new PatternWindow(this); - _patternWindow.SetColumnizer(CurrentColumnizer); - //this.patternWindow.SetBlockList(blockList); - _patternWindow.SetFont(Preferences.fontName, Preferences.fontSize); - _patternWindow.Fuzzy = _patternArgs.Fuzzy; - _patternWindow.MaxDiff = _patternArgs.MaxDiffInBlock; - _patternWindow.MaxMisses = _patternArgs.MaxMisses; - _patternWindow.Weight = _patternArgs.MinWeight; - //this.patternWindow.Show(); + tableLayoutPanel1.ColumnStyles[1].Width = 0; } - private void TestStatistic (PatternArgs patternArgs) - { - var beginLine = patternArgs.StartLine; - _logger.Info("TestStatistics() called with start line {0}", beginLine); + _timeSpreadCalc.Enabled = show; + } - _patternArgs = patternArgs; + protected internal void AddTempFileTab (string fileName, string title) + { + _parentLogTabWin.AddTempFileTab(fileName, title); + } - var num = beginLine + 1; //this.dataGridView.RowCount; + private void InitPatternWindow () + { + //PatternStatistic(this.patternArgs); + _patternWindow = new PatternWindow(this); + _patternWindow.SetColumnizer(CurrentColumnizer); + //this.patternWindow.SetBlockList(blockList); + _patternWindow.SetFont(Preferences.fontName, Preferences.fontSize); + _patternWindow.Fuzzy = _patternArgs.Fuzzy; + _patternWindow.MaxDiff = _patternArgs.MaxDiffInBlock; + _patternWindow.MaxMisses = _patternArgs.MaxMisses; + _patternWindow.Weight = _patternArgs.MinWeight; + //this.patternWindow.Show(); + } - _progressEventArgs.MinValue = 0; - _progressEventArgs.MaxValue = dataGridView.RowCount; - _progressEventArgs.Value = beginLine; - _progressEventArgs.Visible = true; - SendProgressBarUpdate(); + private void TestStatistic (PatternArgs patternArgs) + { + var beginLine = patternArgs.StartLine; + _logger.Info("TestStatistics() called with start line {0}", beginLine); - PrepareDict(); - ResetCache(num); + _patternArgs = patternArgs; - Dictionary processedLinesDict = []; - List blockList = []; - var blockId = 0; - _isSearching = true; - _shouldCancel = false; - var searchLine = -1; - for (var i = beginLine; i < num && !_shouldCancel; ++i) + var num = beginLine + 1; //this.dataGridView.RowCount; + + _progressEventArgs.MinValue = 0; + _progressEventArgs.MaxValue = dataGridView.RowCount; + _progressEventArgs.Value = beginLine; + _progressEventArgs.Visible = true; + SendProgressBarUpdate(); + + PrepareDict(); + ResetCache(num); + + Dictionary processedLinesDict = []; + List blockList = []; + var blockId = 0; + _isSearching = true; + _shouldCancel = false; + var searchLine = -1; + for (var i = beginLine; i < num && !_shouldCancel; ++i) + { + if (processedLinesDict.ContainsKey(i)) { - if (processedLinesDict.ContainsKey(i)) - { - continue; - } + continue; + } - PatternBlock block; - var maxBlockLen = patternArgs.EndLine - patternArgs.StartLine; - //int searchLine = i + 1; - _logger.Debug("TestStatistic(): i={0} searchLine={1}", i, searchLine); - //bool firstBlock = true; - searchLine++; - UpdateProgressBar(searchLine); - while (!_shouldCancel && - (block = - DetectBlock(i, searchLine, maxBlockLen, _patternArgs.MaxDiffInBlock, - _patternArgs.MaxMisses, - processedLinesDict)) != null) - { - _logger.Debug("Found block: {0}", block); - if (block.weigth >= _patternArgs.MinWeight) - { - //PatternBlock existingBlock = FindExistingBlock(block, blockList); - //if (existingBlock != null) - //{ - // if (block.weigth > existingBlock.weigth) - // { - // blockList.Remove(existingBlock); - // blockList.Add(block); - // } - //} - //else - { - blockList.Add(block); - addBlockTargetLinesToDict(processedLinesDict, block); - } - block.blockId = blockId; - //if (firstBlock) - //{ - // addBlockSrcLinesToDict(processedLinesDict, block); - //} - searchLine = block.targetEnd + 1; - } - else + PatternBlock block; + var maxBlockLen = patternArgs.EndLine - patternArgs.StartLine; + //int searchLine = i + 1; + _logger.Debug("TestStatistic(): i={0} searchLine={1}", i, searchLine); + //bool firstBlock = true; + searchLine++; + UpdateProgressBar(searchLine); + while (!_shouldCancel && + (block = + DetectBlock(i, searchLine, maxBlockLen, _patternArgs.MaxDiffInBlock, + _patternArgs.MaxMisses, + processedLinesDict)) != null) + { + _logger.Debug("Found block: {0}", block); + if (block.weigth >= _patternArgs.MinWeight) + { + //PatternBlock existingBlock = FindExistingBlock(block, blockList); + //if (existingBlock != null) + //{ + // if (block.weigth > existingBlock.weigth) + // { + // blockList.Remove(existingBlock); + // blockList.Add(block); + // } + //} + //else { - searchLine = block.targetStart + 1; + blockList.Add(block); + addBlockTargetLinesToDict(processedLinesDict, block); } - - UpdateProgressBar(searchLine); + block.blockId = blockId; + //if (firstBlock) + //{ + // addBlockSrcLinesToDict(processedLinesDict, block); + //} + searchLine = block.targetEnd + 1; + } + else + { + searchLine = block.targetStart + 1; } - blockId++; - } - - _isSearching = false; - _progressEventArgs.MinValue = 0; - _progressEventArgs.MaxValue = 0; - _progressEventArgs.Value = 0; - _progressEventArgs.Visible = false; - SendProgressBarUpdate(); - //if (this.patternWindow.IsDisposed) - //{ - // this.Invoke(new MethodInvoker(CreatePatternWindow)); - //} - _patternWindow.SetBlockList(blockList, _patternArgs); - _logger.Info("TestStatistics() ended"); + UpdateProgressBar(searchLine); + } + + blockId++; } - private void addBlockTargetLinesToDict (Dictionary dict, PatternBlock block) + _isSearching = false; + _progressEventArgs.MinValue = 0; + _progressEventArgs.MaxValue = 0; + _progressEventArgs.Value = 0; + _progressEventArgs.Visible = false; + SendProgressBarUpdate(); + //if (this.patternWindow.IsDisposed) + //{ + // this.Invoke(new MethodInvoker(CreatePatternWindow)); + //} + _patternWindow.SetBlockList(blockList, _patternArgs); + _logger.Info("TestStatistics() ended"); + } + + private void addBlockTargetLinesToDict (Dictionary dict, PatternBlock block) + { + foreach (var lineNum in block.targetLines.Keys) { - foreach (var lineNum in block.targetLines.Keys) + if (!dict.ContainsKey(lineNum)) { - if (!dict.ContainsKey(lineNum)) - { - dict.Add(lineNum, lineNum); - } + dict.Add(lineNum, lineNum); } } + } - //Well keep this for the moment because there is some other commented code which calls this one - private PatternBlock FindExistingBlock (PatternBlock block, List blockList) + //Well keep this for the moment because there is some other commented code which calls this one + private PatternBlock FindExistingBlock (PatternBlock block, List blockList) + { + foreach (PatternBlock searchBlock in blockList) { - foreach (PatternBlock searchBlock in blockList) + if ((block.startLine > searchBlock.startLine && + block.startLine < searchBlock.endLine + || + block.endLine > searchBlock.startLine && + block.endLine < searchBlock.endLine) && block.startLine != searchBlock.startLine && + block.endLine != searchBlock.endLine + ) { - if ((block.startLine > searchBlock.startLine && - block.startLine < searchBlock.endLine - || - block.endLine > searchBlock.startLine && - block.endLine < searchBlock.endLine) && block.startLine != searchBlock.startLine && - block.endLine != searchBlock.endLine - ) - { - return searchBlock; - } + return searchBlock; } + } + + return null; + } + private PatternBlock DetectBlock (int startNum, int startLineToSearch, int maxBlockLen, int maxDiffInBlock, + int maxMisses, Dictionary processedLinesDict) + { + var targetLine = FindSimilarLine(startNum, startLineToSearch, processedLinesDict); + if (targetLine == -1) + { return null; } - private PatternBlock DetectBlock (int startNum, int startLineToSearch, int maxBlockLen, int maxDiffInBlock, - int maxMisses, Dictionary processedLinesDict) + PatternBlock block = new(); + block.startLine = startNum; + var srcLine = block.startLine; + block.targetStart = targetLine; + var srcMisses = 0; + block.srcLines.Add(srcLine, srcLine); + //block.targetLines.Add(targetLine, targetLine); + var len = 0; + QualityInfo qi = new(); + qi.quality = block.weigth; + block.qualityInfoList[targetLine] = qi; + + while (!_shouldCancel) { - var targetLine = FindSimilarLine(startNum, startLineToSearch, processedLinesDict); - if (targetLine == -1) + srcLine++; + len++; + //if (srcLine >= block.targetStart) + // break; // prevent to search in the own block + if (maxBlockLen > 0 && len > maxBlockLen) { - return null; + break; } - PatternBlock block = new(); - block.startLine = startNum; - var srcLine = block.startLine; - block.targetStart = targetLine; - var srcMisses = 0; - block.srcLines.Add(srcLine, srcLine); - //block.targetLines.Add(targetLine, targetLine); - var len = 0; - QualityInfo qi = new(); - qi.quality = block.weigth; - block.qualityInfoList[targetLine] = qi; - - while (!_shouldCancel) + var nextTargetLine = FindSimilarLine(srcLine, targetLine + 1, processedLinesDict); + if (nextTargetLine > -1 && nextTargetLine - targetLine - 1 <= maxDiffInBlock) { - srcLine++; - len++; - //if (srcLine >= block.targetStart) - // break; // prevent to search in the own block - if (maxBlockLen > 0 && len > maxBlockLen) - { - break; - } - - var nextTargetLine = FindSimilarLine(srcLine, targetLine + 1, processedLinesDict); - if (nextTargetLine > -1 && nextTargetLine - targetLine - 1 <= maxDiffInBlock) - { - block.weigth += maxDiffInBlock - (nextTargetLine - targetLine - 1) + 1; - block.endLine = srcLine; - //block.targetLines.Add(nextTargetLine, nextTargetLine); - block.srcLines.Add(srcLine, srcLine); - if (nextTargetLine - targetLine > 1) - { - var tempWeight = block.weigth; - for (var tl = targetLine + 1; tl < nextTargetLine; ++tl) - { - qi = new QualityInfo(); - qi.quality = --tempWeight; - block.qualityInfoList[tl] = qi; - } - } - - targetLine = nextTargetLine; - qi = new QualityInfo(); - qi.quality = block.weigth; - block.qualityInfoList[targetLine] = qi; - } - else + block.weigth += maxDiffInBlock - (nextTargetLine - targetLine - 1) + 1; + block.endLine = srcLine; + //block.targetLines.Add(nextTargetLine, nextTargetLine); + block.srcLines.Add(srcLine, srcLine); + if (nextTargetLine - targetLine > 1) { - srcMisses++; - block.weigth--; - targetLine++; - qi = new QualityInfo(); - qi.quality = block.weigth; - block.qualityInfoList[targetLine] = qi; - if (srcMisses > maxMisses) + var tempWeight = block.weigth; + for (var tl = targetLine + 1; tl < nextTargetLine; ++tl) { - break; + qi = new QualityInfo(); + qi.quality = --tempWeight; + block.qualityInfoList[tl] = qi; } } - } - block.targetEnd = targetLine; - qi = new QualityInfo(); - qi.quality = block.weigth; - block.qualityInfoList[targetLine] = qi; - for (var k = block.targetStart; k <= block.targetEnd; ++k) + targetLine = nextTargetLine; + qi = new QualityInfo(); + qi.quality = block.weigth; + block.qualityInfoList[targetLine] = qi; + } + else { - block.targetLines.Add(k, k); + srcMisses++; + block.weigth--; + targetLine++; + qi = new QualityInfo(); + qi.quality = block.weigth; + block.qualityInfoList[targetLine] = qi; + if (srcMisses > maxMisses) + { + break; + } } - - return block; } - private void PrepareDict () + block.targetEnd = targetLine; + qi = new QualityInfo(); + qi.quality = block.weigth; + block.qualityInfoList[targetLine] = qi; + for (var k = block.targetStart; k <= block.targetEnd; ++k) { - _lineHashList.Clear(); - Regex regex = new("\\d"); - Regex regex2 = new("\\S"); + block.targetLines.Add(k, k); + } - var num = _logFileReader.LineCount; - for (var i = 0; i < num; ++i) - { - var msg = GetMsgForLine(i); - if (msg != null) - { - msg = msg.ToLower(); - msg = regex.Replace(msg, "0"); - msg = regex2.Replace(msg, " "); - var chars = msg.ToCharArray(); - var value = 0; - var numOfE = 0; - var numOfA = 0; - var numOfI = 0; - foreach (var t in chars) - { - value += t; - switch (t) - { - case 'e': - numOfE++; - break; - case 'a': - numOfA++; - break; - case 'i': - numOfI++; - break; - } - } + return block; + } - value += numOfE * 30; - value += numOfA * 20; - value += numOfI * 10; - _lineHashList.Add(value); + private void PrepareDict () + { + _lineHashList.Clear(); + Regex regex = new("\\d"); + Regex regex2 = new("\\S"); + + var num = _logFileReader.LineCount; + for (var i = 0; i < num; ++i) + { + var msg = GetMsgForLine(i); + if (msg != null) + { + msg = msg.ToLower(); + msg = regex.Replace(msg, "0"); + msg = regex2.Replace(msg, " "); + var chars = msg.ToCharArray(); + var value = 0; + var numOfE = 0; + var numOfA = 0; + var numOfI = 0; + foreach (var t in chars) + { + value += t; + switch (t) + { + case 'e': + numOfE++; + break; + case 'a': + numOfA++; + break; + case 'i': + numOfI++; + break; + } } + + value += numOfE * 30; + value += numOfA * 20; + value += numOfI * 10; + _lineHashList.Add(value); } } + } - private int _FindSimilarLine (int srcLine, int startLine) - { - var value = _lineHashList[srcLine]; + private int _FindSimilarLine (int srcLine, int startLine) + { + var value = _lineHashList[srcLine]; - var num = _lineHashList.Count; - for (var i = startLine; i < num; ++i) + var num = _lineHashList.Count; + for (var i = startLine; i < num; ++i) + { + if (Math.Abs(_lineHashList[i] - value) < 3) { - if (Math.Abs(_lineHashList[i] - value) < 3) - { - return i; - } + return i; } - - return -1; } - // int[,] similarCache; + return -1; + } + + // int[,] similarCache; + + private void ResetCache (int num) + { + //this.similarCache = new int[num, num]; + //for (int i = 0; i < num; ++i) + //{ + // for (int j = 0; j < num; j++) + // { + // this.similarCache[i, j] = -1; + // } + //} + } + + private int FindSimilarLine (int srcLine, int startLine, Dictionary processedLinesDict) + { + var threshold = _patternArgs.Fuzzy; + + var prepared = false; + Regex regex = null; + Regex regex2 = null; + string msgToFind = null; + CultureInfo culture = CultureInfo.CurrentCulture; - private void ResetCache (int num) + var num = _logFileReader.LineCount; + for (var i = startLine; i < num; ++i) { - //this.similarCache = new int[num, num]; - //for (int i = 0; i < num; ++i) + if (processedLinesDict.ContainsKey(i)) + { + continue; + } + + //if (this.similarCache[srcLine, i] != -1) //{ - // for (int j = 0; j < num; j++) + // if (this.similarCache[srcLine, i] < threshold) // { - // this.similarCache[i, j] = -1; + // return i; // } //} - } - - private int FindSimilarLine (int srcLine, int startLine, Dictionary processedLinesDict) - { - var threshold = _patternArgs.Fuzzy; - - var prepared = false; - Regex regex = null; - Regex regex2 = null; - string msgToFind = null; - CultureInfo culture = CultureInfo.CurrentCulture; - - var num = _logFileReader.LineCount; - for (var i = startLine; i < num; ++i) + //else { - if (processedLinesDict.ContainsKey(i)) + if (!prepared) { - continue; + msgToFind = GetMsgForLine(srcLine); + regex = new Regex("\\d"); + regex2 = new Regex("\\W"); + msgToFind = msgToFind.ToLower(culture); + msgToFind = regex.Replace(msgToFind, "0"); + msgToFind = regex2.Replace(msgToFind, " "); + prepared = true; } - //if (this.similarCache[srcLine, i] != -1) - //{ - // if (this.similarCache[srcLine, i] < threshold) - // { - // return i; - // } - //} - //else + var msg = GetMsgForLine(i); + if (msg != null) { - if (!prepared) + msg = regex.Replace(msg, "0"); + msg = regex2.Replace(msg, " "); + var lenDiff = Math.Abs(msg.Length - msgToFind.Length); + if (lenDiff > threshold) { - msgToFind = GetMsgForLine(srcLine); - regex = new Regex("\\d"); - regex2 = new Regex("\\W"); - msgToFind = msgToFind.ToLower(culture); - msgToFind = regex.Replace(msgToFind, "0"); - msgToFind = regex2.Replace(msgToFind, " "); - prepared = true; + //this.similarCache[srcLine, i] = lenDiff; + continue; } - var msg = GetMsgForLine(i); - if (msg != null) + msg = msg.ToLower(culture); + var distance = Util.YetiLevenshtein(msgToFind, msg); + //this.similarCache[srcLine, i] = distance; + if (distance < threshold) { - msg = regex.Replace(msg, "0"); - msg = regex2.Replace(msg, " "); - var lenDiff = Math.Abs(msg.Length - msgToFind.Length); - if (lenDiff > threshold) - { - //this.similarCache[srcLine, i] = lenDiff; - continue; - } - - msg = msg.ToLower(culture); - var distance = Util.YetiLevenshtein(msgToFind, msg); - //this.similarCache[srcLine, i] = distance; - if (distance < threshold) - { - return i; - } + return i; } } } - - return -1; } - private string GetMsgForLine (int i) + return -1; + } + + private string GetMsgForLine (int i) + { + ILogLine line = _logFileReader.GetLogLine(i); + ILogLineColumnizer columnizer = CurrentColumnizer; + ColumnizerCallback callback = new(this); + IColumnizedLogLine cols = columnizer.SplitLine(callback, line); + return cols.ColumnValues.Last().FullValue; + } + + private void ChangeRowHeight (bool decrease) + { + var rowNum = dataGridView.CurrentCellAddress.Y; + if (rowNum < 0 || rowNum >= dataGridView.RowCount) { - ILogLine line = _logFileReader.GetLogLine(i); - ILogLineColumnizer columnizer = CurrentColumnizer; - ColumnizerCallback callback = new(this); - IColumnizedLogLine cols = columnizer.SplitLine(callback, line); - return cols.ColumnValues.Last().FullValue; + return; } - private void ChangeRowHeight (bool decrease) + if (decrease) { - var rowNum = dataGridView.CurrentCellAddress.Y; - if (rowNum < 0 || rowNum >= dataGridView.RowCount) + if (!_rowHeightList.ContainsKey(rowNum)) { return; } - - if (decrease) - { - if (!_rowHeightList.ContainsKey(rowNum)) - { - return; - } - else - { - RowHeightEntry entry = _rowHeightList[rowNum]; - entry.Height -= _lineHeight; - if (entry.Height <= _lineHeight) - { - _rowHeightList.Remove(rowNum); - } - } - } else { - RowHeightEntry entry; - if (!_rowHeightList.ContainsKey(rowNum)) - { - entry = new RowHeightEntry(); - entry.LineNum = rowNum; - entry.Height = _lineHeight; - _rowHeightList[rowNum] = entry; - } - else + RowHeightEntry entry = _rowHeightList[rowNum]; + entry.Height -= _lineHeight; + if (entry.Height <= _lineHeight) { - entry = _rowHeightList[rowNum]; + _rowHeightList.Remove(rowNum); } - - entry.Height += _lineHeight; - } - - dataGridView.UpdateRowHeightInfo(rowNum, false); - if (rowNum == dataGridView.RowCount - 1 && _guiStateArgs.FollowTail) - { - dataGridView.FirstDisplayedScrollingRowIndex = rowNum; } - - dataGridView.Refresh(); } - - private int GetRowHeight (int rowNum) + else { - if (_rowHeightList.ContainsKey(rowNum)) + RowHeightEntry entry; + if (!_rowHeightList.ContainsKey(rowNum)) { - return _rowHeightList[rowNum].Height; + entry = new RowHeightEntry(); + entry.LineNum = rowNum; + entry.Height = _lineHeight; + _rowHeightList[rowNum] = entry; } else { - return _lineHeight; + entry = _rowHeightList[rowNum]; } + + entry.Height += _lineHeight; } - private void AddBookmarkAtLineSilently (int lineNum) + dataGridView.UpdateRowHeightInfo(rowNum, false); + if (rowNum == dataGridView.RowCount - 1 && _guiStateArgs.FollowTail) { - if (!_bookmarkProvider.IsBookmarkAtLine(lineNum)) - { - _bookmarkProvider.AddBookmark(new Bookmark(lineNum)); - } + dataGridView.FirstDisplayedScrollingRowIndex = rowNum; } - private void AddBookmarkAndEditComment () - { - var lineNum = dataGridView.CurrentCellAddress.Y; - if (!_bookmarkProvider.IsBookmarkAtLine(lineNum)) - { - ToggleBookmark(); - } + dataGridView.Refresh(); + } - BookmarkComment(_bookmarkProvider.GetBookmarkForLine(lineNum)); + private int GetRowHeight (int rowNum) + { + if (_rowHeightList.ContainsKey(rowNum)) + { + return _rowHeightList[rowNum].Height; } - - private void AddBookmarkComment (string text) + else { - var lineNum = dataGridView.CurrentCellAddress.Y; - Bookmark bookmark; - if (!_bookmarkProvider.IsBookmarkAtLine(lineNum)) - { - _bookmarkProvider.AddBookmark(bookmark = new Bookmark(lineNum)); - } - else - { - bookmark = _bookmarkProvider.GetBookmarkForLine(lineNum); - } + return _lineHeight; + } + } - bookmark.Text += text; - dataGridView.Refresh(); - filterGridView.Refresh(); - OnBookmarkTextChanged(bookmark); + private void AddBookmarkAtLineSilently (int lineNum) + { + if (!_bookmarkProvider.IsBookmarkAtLine(lineNum)) + { + _bookmarkProvider.AddBookmark(new Bookmark(lineNum)); } + } - private void MarkCurrentFilterRange () + private void AddBookmarkAndEditComment () + { + var lineNum = dataGridView.CurrentCellAddress.Y; + if (!_bookmarkProvider.IsBookmarkAtLine(lineNum)) { - _filterParams.RangeSearchText = filterRangeComboBox.Text; - ColumnizerCallback callback = new(this); - RangeFinder rangeFinder = new(_filterParams, callback); - Core.Entities.Range range = rangeFinder.FindRange(dataGridView.CurrentCellAddress.Y); - if (range != null) - { - SetCellSelectionMode(false); - _noSelectionUpdates = true; - for (var i = range.StartLine; i <= range.EndLine; ++i) - { - dataGridView.Rows[i].Selected = true; - } + ToggleBookmark(); + } - _noSelectionUpdates = false; - UpdateSelectionDisplay(); - } + BookmarkComment(_bookmarkProvider.GetBookmarkForLine(lineNum)); + } + + private void AddBookmarkComment (string text) + { + var lineNum = dataGridView.CurrentCellAddress.Y; + Bookmark bookmark; + if (!_bookmarkProvider.IsBookmarkAtLine(lineNum)) + { + _bookmarkProvider.AddBookmark(bookmark = new Bookmark(lineNum)); } + else + { + bookmark = _bookmarkProvider.GetBookmarkForLine(lineNum); + } + + bookmark.Text += text; + dataGridView.Refresh(); + filterGridView.Refresh(); + OnBookmarkTextChanged(bookmark); + } - private void RemoveTempHighlights () + private void MarkCurrentFilterRange () + { + _filterParams.RangeSearchText = filterRangeComboBox.Text; + ColumnizerCallback callback = new(this); + RangeFinder rangeFinder = new(_filterParams, callback); + Core.Entities.Range range = rangeFinder.FindRange(dataGridView.CurrentCellAddress.Y); + if (range != null) { - lock (_tempHighlightEntryListLock) + SetCellSelectionMode(false); + _noSelectionUpdates = true; + for (var i = range.StartLine; i <= range.EndLine; ++i) { - _tempHighlightEntryList.Clear(); + dataGridView.Rows[i].Selected = true; } - RefreshAllGrids(); + _noSelectionUpdates = false; + UpdateSelectionDisplay(); } + } - private void ToggleHighlightPanel (bool open) + private void RemoveTempHighlights () + { + lock (_tempHighlightEntryListLock) { - highlightSplitContainer.Panel2Collapsed = !open; - btnToggleHighlightPanel.Image = open - ? new Bitmap(_panelCloseButtonImage, new Size(btnToggleHighlightPanel.Size.Height, btnToggleHighlightPanel.Size.Height)) - : new Bitmap(_panelOpenButtonImage, new Size(btnToggleHighlightPanel.Size.Height, btnToggleHighlightPanel.Size.Height)); + _tempHighlightEntryList.Clear(); } - private void SetBookmarksForSelectedFilterLines () - { - lock (_filterResultList) - { - foreach (DataGridViewRow row in filterGridView.SelectedRows) - { - var lineNum = _filterResultList[row.Index]; - AddBookmarkAtLineSilently(lineNum); - } - } + RefreshAllGrids(); + } - dataGridView.Refresh(); - filterGridView.Refresh(); - OnBookmarkAdded(); - } + private void ToggleHighlightPanel (bool open) + { + highlightSplitContainer.Panel2Collapsed = !open; + btnToggleHighlightPanel.Image = open + ? new Bitmap(_panelCloseButtonImage, new Size(btnToggleHighlightPanel.Size.Height, btnToggleHighlightPanel.Size.Height)) + : new Bitmap(_panelOpenButtonImage, new Size(btnToggleHighlightPanel.Size.Height, btnToggleHighlightPanel.Size.Height)); + } - private void SetDefaultHighlightGroup () + private void SetBookmarksForSelectedFilterLines () + { + lock (_filterResultList) { - HighlightGroup group = _parentLogTabWin.FindHighlightGroupByFileMask(FileName); - if (group != null) - { - SetCurrentHighlightGroup(group.GroupName); - } - else + foreach (DataGridViewRow row in filterGridView.SelectedRows) { - SetCurrentHighlightGroup("[Default]"); + var lineNum = _filterResultList[row.Index]; + AddBookmarkAtLineSilently(lineNum); } } - private void HandleChangedFilterOnLoadSetting () + dataGridView.Refresh(); + filterGridView.Refresh(); + OnBookmarkAdded(); + } + + private void SetDefaultHighlightGroup () + { + HighlightGroup group = _parentLogTabWin.FindHighlightGroupByFileMask(FileName); + if (group != null) + { + SetCurrentHighlightGroup(group.GroupName); + } + else { - _parentLogTabWin.Preferences.isFilterOnLoad = filterOnLoadCheckBox.Checked; - _parentLogTabWin.Preferences.isAutoHideFilterList = hideFilterListOnLoadCheckBox.Checked; - OnFilterListChanged(this); + SetCurrentHighlightGroup("[Default]"); } + } - private void FireCancelHandlers () + private void HandleChangedFilterOnLoadSetting () + { + _parentLogTabWin.Preferences.isFilterOnLoad = filterOnLoadCheckBox.Checked; + _parentLogTabWin.Preferences.isAutoHideFilterList = hideFilterListOnLoadCheckBox.Checked; + OnFilterListChanged(this); + } + + private void FireCancelHandlers () + { + lock (_cancelHandlerList) { - lock (_cancelHandlerList) + foreach (var handler in _cancelHandlerList) { - foreach (var handler in _cancelHandlerList) - { - handler.EscapePressed(); - } + handler.EscapePressed(); } } + } - private void SyncOtherWindows (DateTime timestamp) + private void SyncOtherWindows (DateTime timestamp) + { + lock (_timeSyncListLock) { - lock (_timeSyncListLock) - { - TimeSyncList?.NavigateToTimestamp(timestamp, this); - } + TimeSyncList?.NavigateToTimestamp(timestamp, this); } + } - private void AddSlaveToTimesync (LogWindow slave) + private void AddSlaveToTimesync (LogWindow slave) + { + lock (_timeSyncListLock) { - lock (_timeSyncListLock) + if (TimeSyncList == null) { - if (TimeSyncList == null) + if (slave.TimeSyncList == null) { - if (slave.TimeSyncList == null) - { - TimeSyncList = new TimeSyncList(); - TimeSyncList.AddWindow(this); - } - else - { - TimeSyncList = slave.TimeSyncList; - } - - var currentLineNum = dataGridView.CurrentCellAddress.Y; - var refLine = currentLineNum; - DateTime timeStamp = GetTimestampForLine(ref refLine, true); - if (!timeStamp.Equals(DateTime.MinValue) && !_shouldTimestampDisplaySyncingCancel) - { - TimeSyncList.CurrentTimestamp = timeStamp; - } + TimeSyncList = new TimeSyncList(); + TimeSyncList.AddWindow(this); + } + else + { + TimeSyncList = slave.TimeSyncList; + } - TimeSyncList.WindowRemoved += OnTimeSyncListWindowRemoved; + var currentLineNum = dataGridView.CurrentCellAddress.Y; + var refLine = currentLineNum; + DateTime timeStamp = GetTimestampForLine(ref refLine, true); + if (!timeStamp.Equals(DateTime.MinValue) && !_shouldTimestampDisplaySyncingCancel) + { + TimeSyncList.CurrentTimestamp = timeStamp; } - } - slave.AddToTimeSync(this); - OnSyncModeChanged(); + TimeSyncList.WindowRemoved += OnTimeSyncListWindowRemoved; + } } - private void FreeSlaveFromTimesync (LogWindow slave) - { - slave.FreeFromTimeSync(); - } + slave.AddToTimeSync(this); + OnSyncModeChanged(); + } - private void OnSyncModeChanged () - { - SyncModeChanged?.Invoke(this, new SyncModeEventArgs(IsTimeSynced)); - } + private void FreeSlaveFromTimesync (LogWindow slave) + { + slave.FreeFromTimeSync(); + } - private void AddSearchHitHighlightEntry (SearchParams para) - { - HighlightEntry he = new() - { - SearchText = para.SearchText, - ForegroundColor = Color.Red, - BackgroundColor = Color.Yellow, - IsRegEx = para.IsRegex, - IsCaseSensitive = para.IsCaseSensitive, - IsLedSwitch = false, - IsStopTail = false, - IsSetBookmark = false, - IsActionEntry = false, - ActionEntry = null, - IsWordMatch = true, - IsSearchHit = true - }; + private void OnSyncModeChanged () + { + SyncModeChanged?.Invoke(this, new SyncModeEventArgs(IsTimeSynced)); + } - lock (_tempHighlightEntryListLock) - { - _tempHighlightEntryList.Add(he); - } + private void AddSearchHitHighlightEntry (SearchParams para) + { + HighlightEntry he = new() + { + SearchText = para.SearchText, + ForegroundColor = Color.Red, + BackgroundColor = Color.Yellow, + IsRegEx = para.IsRegex, + IsCaseSensitive = para.IsCaseSensitive, + IsLedSwitch = false, + IsStopTail = false, + IsSetBookmark = false, + IsActionEntry = false, + ActionEntry = null, + IsWordMatch = true, + IsSearchHit = true + }; - RefreshAllGrids(); + lock (_tempHighlightEntryListLock) + { + _tempHighlightEntryList.Add(he); } - private void RemoveAllSearchHighlightEntries () + RefreshAllGrids(); + } + + private void RemoveAllSearchHighlightEntries () + { + lock (_tempHighlightEntryListLock) { - lock (_tempHighlightEntryListLock) + List newList = []; + foreach (HighlightEntry he in _tempHighlightEntryList) { - List newList = []; - foreach (HighlightEntry he in _tempHighlightEntryList) + if (!he.IsSearchHit) { - if (!he.IsSearchHit) - { - newList.Add(he); - } + newList.Add(he); } - - _tempHighlightEntryList = newList; } - RefreshAllGrids(); + _tempHighlightEntryList = newList; } - private DataGridViewColumn GetColumnByName (BufferedDataGridView dataGridView, string name) + RefreshAllGrids(); + } + + private DataGridViewColumn GetColumnByName (BufferedDataGridView dataGridView, string name) + { + foreach (DataGridViewColumn col in dataGridView.Columns) { - foreach (DataGridViewColumn col in dataGridView.Columns) + if (col.HeaderText.Equals(name)) { - if (col.HeaderText.Equals(name)) - { - return col; - } + return col; } - - return null; } - private void SelectColumn () + return null; + } + + private void SelectColumn () + { + var colName = columnComboBox.SelectedItem as string; + DataGridViewColumn col = GetColumnByName(dataGridView, colName); + if (col != null && !col.Frozen) { - var colName = columnComboBox.SelectedItem as string; - DataGridViewColumn col = GetColumnByName(dataGridView, colName); - if (col != null && !col.Frozen) + dataGridView.FirstDisplayedScrollingColumnIndex = col.Index; + var currentLine = dataGridView.CurrentCellAddress.Y; + if (currentLine >= 0) { - dataGridView.FirstDisplayedScrollingColumnIndex = col.Index; - var currentLine = dataGridView.CurrentCellAddress.Y; - if (currentLine >= 0) - { - dataGridView.CurrentCell = dataGridView.Rows[dataGridView.CurrentCellAddress.Y].Cells[col.Index]; - } + dataGridView.CurrentCell = dataGridView.Rows[dataGridView.CurrentCellAddress.Y].Cells[col.Index]; } } + } - #endregion + #endregion - } } \ No newline at end of file diff --git a/src/LogExpert.UI/Controls/LogWindow/LogWindowPublic.cs b/src/LogExpert.UI/Controls/LogWindow/LogWindowPublic.cs index afb29b12..20e1451e 100644 --- a/src/LogExpert.UI/Controls/LogWindow/LogWindowPublic.cs +++ b/src/LogExpert.UI/Controls/LogWindow/LogWindowPublic.cs @@ -1,4 +1,6 @@ -using LogExpert.Classes.Filter; +using System.Text; + +using LogExpert.Classes.Filter; using LogExpert.Core.Classes; using LogExpert.Core.Classes.Bookmark; using LogExpert.Core.Classes.Columnizer; @@ -10,1833 +12,1831 @@ using LogExpert.Core.EventArguments; using LogExpert.Dialogs; using LogExpert.UI.Entities; -using System.Text; -namespace LogExpert.UI.Controls.LogWindow +namespace LogExpert.UI.Controls.LogWindow; + +partial class LogWindow { - partial class LogWindow + #region Public methods + + public void LoadFile (string fileName, EncodingOptions encodingOptions) { - #region Public methods + EnterLoadFileStatus(); - public void LoadFile(string fileName, EncodingOptions encodingOptions) + if (fileName != null) { - EnterLoadFileStatus(); + FileName = fileName; + EncodingOptions = encodingOptions; - if (fileName != null) + if (_logFileReader != null) { - FileName = fileName; - EncodingOptions = encodingOptions; - - if (_logFileReader != null) - { - _logFileReader.StopMonitoringAsync(); - UnRegisterLogFileReaderEvents(); - } + _logFileReader.StopMonitoringAsync(); + UnRegisterLogFileReaderEvents(); + } - // - // isUsingDefaultColumnizer is to enable automatically find the best columnizer. - // When a new log file is opened, and no Columnizer can be chose by file mask, - // this flag will enable find a columnizer automatically. - // Current solution is not elegant. - // Since the refactory will involving a lot of work, we can plan it in the future. - // One possible solution is, using raw file stream to read the sample lines to help - // the ColumnizerPicker to determine the priority. - // - bool isUsingDefaultColumnizer = false; - if (!LoadPersistenceOptions()) + // + // isUsingDefaultColumnizer is to enable automatically find the best columnizer. + // When a new log file is opened, and no Columnizer can be chose by file mask, + // this flag will enable find a columnizer automatically. + // Current solution is not elegant. + // Since the refactory will involving a lot of work, we can plan it in the future. + // One possible solution is, using raw file stream to read the sample lines to help + // the ColumnizerPicker to determine the priority. + // + var isUsingDefaultColumnizer = false; + if (!LoadPersistenceOptions()) + { + if (!IsTempFile) { - if (!IsTempFile) + ILogLineColumnizer columnizer = FindColumnizer(); + if (columnizer != null) { - ILogLineColumnizer columnizer = FindColumnizer(); - if (columnizer != null) + if (_reloadMemento == null) { - if (_reloadMemento == null) - { - //TODO this needs to be refactored - var directory = ConfigManager.Settings.Preferences.PortableMode ? ConfigManager.PortableModeDir : ConfigManager.ConfigDir; + //TODO this needs to be refactored + var directory = ConfigManager.Settings.Preferences.PortableMode ? ConfigManager.PortableModeDir : ConfigManager.ConfigDir; - columnizer = ColumnizerPicker.CloneColumnizer(columnizer, directory); - } - } - else - { - isUsingDefaultColumnizer = true; + columnizer = ColumnizerPicker.CloneColumnizer(columnizer, directory); } - PreSelectColumnizer(columnizer); } - SetDefaultHighlightGroup(); + else + { + isUsingDefaultColumnizer = true; + } + PreSelectColumnizer(columnizer); } + SetDefaultHighlightGroup(); + } - // this may be set after loading persistence data - if (_fileNames != null && IsMultiFile) - { - LoadFilesAsMulti(_fileNames, EncodingOptions); - return; - } + // this may be set after loading persistence data + if (_fileNames != null && IsMultiFile) + { + LoadFilesAsMulti(_fileNames, EncodingOptions); + return; + } - _columnCache = new ColumnCache(); + _columnCache = new ColumnCache(); - try - { - _logFileReader = new(fileName, EncodingOptions, IsMultiFile, Preferences.bufferCount, Preferences.linesPerBuffer, _multiFileOptions, PluginRegistry.PluginRegistry.Instance) - { - UseNewReader = !Preferences.useLegacyReader - }; - } - catch (LogFileException lfe) + try + { + _logFileReader = new(fileName, EncodingOptions, IsMultiFile, Preferences.bufferCount, Preferences.linesPerBuffer, _multiFileOptions, PluginRegistry.PluginRegistry.Instance) { - _logger.Error(lfe); - MessageBox.Show("Cannot load file\n" + lfe.Message, "LogExpert"); - _ = BeginInvoke(new FunctionWith1BoolParam(Close), true); - _isLoadError = true; - return; - } + UseNewReader = !Preferences.useLegacyReader + }; + } + catch (LogFileException lfe) + { + _logger.Error(lfe); + MessageBox.Show("Cannot load file\n" + lfe.Message, "LogExpert"); + _ = BeginInvoke(new FunctionWith1BoolParam(Close), true); + _isLoadError = true; + return; + } - if (CurrentColumnizer is ILogLineXmlColumnizer xmlColumnizer) - { - _logFileReader.IsXmlMode = true; - _logFileReader.XmlLogConfig = xmlColumnizer.GetXmlLogConfiguration(); - } + if (CurrentColumnizer is ILogLineXmlColumnizer xmlColumnizer) + { + _logFileReader.IsXmlMode = true; + _logFileReader.XmlLogConfig = xmlColumnizer.GetXmlLogConfiguration(); + } - if (_forcedColumnizerForLoading != null) - { - CurrentColumnizer = _forcedColumnizerForLoading; - } + if (_forcedColumnizerForLoading != null) + { + CurrentColumnizer = _forcedColumnizerForLoading; + } - if (CurrentColumnizer is IPreProcessColumnizer processColumnizer) - { - _logFileReader.PreProcessColumnizer = processColumnizer; - } - else - { - _logFileReader.PreProcessColumnizer = null; - } + if (CurrentColumnizer is IPreProcessColumnizer processColumnizer) + { + _logFileReader.PreProcessColumnizer = processColumnizer; + } + else + { + _logFileReader.PreProcessColumnizer = null; + } - RegisterLogFileReaderEvents(); - _logger.Info($"Loading logfile: {fileName}"); - _logFileReader.StartMonitoring(); + RegisterLogFileReaderEvents(); + _logger.Info($"Loading logfile: {fileName}"); + _logFileReader.StartMonitoring(); - if (isUsingDefaultColumnizer) + if (isUsingDefaultColumnizer) + { + if (Preferences.autoPick) { - if (Preferences.autoPick) - { - ILogLineColumnizer newColumnizer = ColumnizerPicker.FindBetterColumnizer(FileName, _logFileReader, CurrentColumnizer, PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers); + ILogLineColumnizer newColumnizer = ColumnizerPicker.FindBetterColumnizer(FileName, _logFileReader, CurrentColumnizer, PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers); - if (newColumnizer != null) - { - _logger.Debug($"Picked new columnizer '{newColumnizer}'"); + if (newColumnizer != null) + { + _logger.Debug($"Picked new columnizer '{newColumnizer}'"); - PreSelectColumnizer(newColumnizer); - } + PreSelectColumnizer(newColumnizer); } } } } + } - public void LoadFilesAsMulti(string[] fileNames, EncodingOptions encodingOptions) - { - _logger.Info("Loading given files as MultiFile:"); + public void LoadFilesAsMulti (string[] fileNames, EncodingOptions encodingOptions) + { + _logger.Info("Loading given files as MultiFile:"); - EnterLoadFileStatus(); + EnterLoadFileStatus(); - foreach (string name in fileNames) - { - _logger.Info("File: {0}", name); - } + foreach (var name in fileNames) + { + _logger.Info("File: {0}", name); + } - if (_logFileReader != null) - { - _logFileReader.StopMonitoring(); - UnRegisterLogFileReaderEvents(); - } + if (_logFileReader != null) + { + _logFileReader.StopMonitoring(); + UnRegisterLogFileReaderEvents(); + } - EncodingOptions = encodingOptions; - _columnCache = new ColumnCache(); + EncodingOptions = encodingOptions; + _columnCache = new ColumnCache(); - _logFileReader = new(fileNames, EncodingOptions, Preferences.bufferCount, Preferences.linesPerBuffer, _multiFileOptions, PluginRegistry.PluginRegistry.Instance) - { - UseNewReader = !Preferences.useLegacyReader - }; + _logFileReader = new(fileNames, EncodingOptions, Preferences.bufferCount, Preferences.linesPerBuffer, _multiFileOptions, PluginRegistry.PluginRegistry.Instance) + { + UseNewReader = !Preferences.useLegacyReader + }; - RegisterLogFileReaderEvents(); - _logFileReader.StartMonitoring(); - FileName = fileNames[^1]; - _fileNames = fileNames; - IsMultiFile = true; - //if (this.isTempFile) - // this.Text = this.tempTitleName; - //else - // this.Text = Util.GetNameFromPath(this.FileName); - } + RegisterLogFileReaderEvents(); + _logFileReader.StartMonitoring(); + FileName = fileNames[^1]; + _fileNames = fileNames; + IsMultiFile = true; + //if (this.isTempFile) + // this.Text = this.tempTitleName; + //else + // this.Text = Util.GetNameFromPath(this.FileName); + } - public string SavePersistenceData(bool force) + public string SavePersistenceData (bool force) + { + if (!force) { - if (!force) - { - if (!Preferences.saveSessions) - { - return null; - } - } - - if (IsTempFile || _isLoadError) + if (!Preferences.saveSessions) { return null; } + } - try - { - PersistenceData persistenceData = GetPersistenceData(); + if (IsTempFile || _isLoadError) + { + return null; + } - if (ForcedPersistenceFileName == null) - { - return Persister.SavePersistenceData(FileName, persistenceData, Preferences); - } + try + { + PersistenceData persistenceData = GetPersistenceData(); - return Persister.SavePersistenceDataWithFixedName(ForcedPersistenceFileName, persistenceData); - } - catch (IOException ex) - { - _logger.Error(ex, "Error saving persistence: "); - } - catch (Exception e) + if (ForcedPersistenceFileName == null) { - MessageBox.Show($"Unexpected error while saving persistence: {e.Message}"); + return Persister.SavePersistenceData(FileName, persistenceData, Preferences); } - return null; + return Persister.SavePersistenceDataWithFixedName(ForcedPersistenceFileName, persistenceData); + } + catch (IOException ex) + { + _logger.Error(ex, "Error saving persistence: "); + } + catch (Exception e) + { + MessageBox.Show($"Unexpected error while saving persistence: {e.Message}"); } - public PersistenceData GetPersistenceData() - { - PersistenceData persistenceData = new() - { - bookmarkList = _bookmarkProvider.BookmarkList, - rowHeightList = _rowHeightList, - multiFile = IsMultiFile, - multiFilePattern = _multiFileOptions.FormatPattern, - multiFileMaxDays = _multiFileOptions.MaxDayTry, - currentLine = dataGridView.CurrentCellAddress.Y, - firstDisplayedLine = dataGridView.FirstDisplayedScrollingRowIndex, - filterVisible = !splitContainerLogWindow.Panel2Collapsed, - filterAdvanced = !advancedFilterSplitContainer.Panel1Collapsed, - filterPosition = splitContainerLogWindow.SplitterDistance, - followTail = _guiStateArgs.FollowTail, - fileName = FileName, - tabName = Text, - sessionFileName = SessionFileName, - columnizerName = CurrentColumnizer.GetName(), - lineCount = _logFileReader.LineCount - }; + return null; + } - _filterParams.IsFilterTail = filterTailCheckBox.Checked; // this option doesnt need a press on 'search' + public PersistenceData GetPersistenceData () + { + PersistenceData persistenceData = new() + { + bookmarkList = _bookmarkProvider.BookmarkList, + rowHeightList = _rowHeightList, + multiFile = IsMultiFile, + multiFilePattern = _multiFileOptions.FormatPattern, + multiFileMaxDays = _multiFileOptions.MaxDayTry, + currentLine = dataGridView.CurrentCellAddress.Y, + firstDisplayedLine = dataGridView.FirstDisplayedScrollingRowIndex, + filterVisible = !splitContainerLogWindow.Panel2Collapsed, + filterAdvanced = !advancedFilterSplitContainer.Panel1Collapsed, + filterPosition = splitContainerLogWindow.SplitterDistance, + followTail = _guiStateArgs.FollowTail, + fileName = FileName, + tabName = Text, + sessionFileName = SessionFileName, + columnizerName = CurrentColumnizer.GetName(), + lineCount = _logFileReader.LineCount + }; + + _filterParams.IsFilterTail = filterTailCheckBox.Checked; // this option doesnt need a press on 'search' + + if (Preferences.saveFilters) + { + List filterList = [_filterParams]; + persistenceData.filterParamsList = filterList; + + foreach (FilterPipe filterPipe in _filterPipeList) + { + FilterTabData data = new() + { + PersistenceData = filterPipe.OwnLogWindow.GetPersistenceData(), + FilterParams = filterPipe.FilterParams + }; + persistenceData.filterTabDataList.Add(data); + } + } - if (Preferences.saveFilters) - { - List filterList = [_filterParams]; - persistenceData.filterParamsList = filterList; + if (_currentHighlightGroup != null) + { + persistenceData.highlightGroupName = _currentHighlightGroup.GroupName; + } - foreach (FilterPipe filterPipe in _filterPipeList) - { - FilterTabData data = new() - { - PersistenceData = filterPipe.OwnLogWindow.GetPersistenceData(), - FilterParams = filterPipe.FilterParams - }; - persistenceData.filterTabDataList.Add(data); - } - } + if (_fileNames != null && IsMultiFile) + { + persistenceData.multiFileNames.AddRange(_fileNames); + } - if (_currentHighlightGroup != null) - { - persistenceData.highlightGroupName = _currentHighlightGroup.GroupName; - } + //persistenceData.showBookmarkCommentColumn = this.bookmarkWindow.ShowBookmarkCommentColumn; + persistenceData.filterSaveListVisible = !highlightSplitContainer.Panel2Collapsed; + persistenceData.encoding = _logFileReader.CurrentEncoding; - if (_fileNames != null && IsMultiFile) - { - persistenceData.multiFileNames.AddRange(_fileNames); - } + return persistenceData; + } + + public void Close (bool dontAsk) + { + Preferences.askForClose = !dontAsk; + Close(); + } - //persistenceData.showBookmarkCommentColumn = this.bookmarkWindow.ShowBookmarkCommentColumn; - persistenceData.filterSaveListVisible = !highlightSplitContainer.Panel2Collapsed; - persistenceData.encoding = _logFileReader.CurrentEncoding; + public void CloseLogWindow () + { + StopTimespreadThread(); + StopTimestampSyncThread(); + StopLogEventWorkerThread(); + _shouldCancel = true; - return persistenceData; + if (_logFileReader != null) + { + UnRegisterLogFileReaderEvents(); + _logFileReader.StopMonitoringAsync(); + //this.logFileReader.DeleteAllContent(); } - public void Close(bool dontAsk) + if (_isLoading) { - Preferences.askForClose = !dontAsk; - Close(); + _waitingForClose = true; } - public void CloseLogWindow() + if (IsTempFile) { - StopTimespreadThread(); - StopTimestampSyncThread(); - StopLogEventWorkerThread(); - _shouldCancel = true; + _logger.Info("Deleting temp file {0}", FileName); - if (_logFileReader != null) + try { - UnRegisterLogFileReaderEvents(); - _logFileReader.StopMonitoringAsync(); - //this.logFileReader.DeleteAllContent(); + File.Delete(FileName); } - - if (_isLoading) + catch (IOException e) { - _waitingForClose = true; + _logger.Error(e, "Error while deleting temp file {0}: {1}", FileName, e); } + } - if (IsTempFile) - { - _logger.Info("Deleting temp file {0}", FileName); + FilterPipe?.CloseAndDisconnect(); + DisconnectFilterPipes(); + } - try - { - File.Delete(FileName); - } - catch (IOException e) - { - _logger.Error(e, "Error while deleting temp file {0}: {1}", FileName, e); - } - } + public void WaitForLoadingFinished () + { + _externaLoadingFinishedEvent.WaitOne(); + } - FilterPipe?.CloseAndDisconnect(); - DisconnectFilterPipes(); - } + public void ForceColumnizer (ILogLineColumnizer columnizer) + { + //TODO this needs to be refactored + var directory = ConfigManager.Settings.Preferences.PortableMode ? ConfigManager.PortableModeDir : ConfigManager.ConfigDir; - public void WaitForLoadingFinished() - { - _externaLoadingFinishedEvent.WaitOne(); - } + _forcedColumnizer = ColumnizerPicker.CloneColumnizer(columnizer, directory); + SetColumnizer(_forcedColumnizer); + } - public void ForceColumnizer(ILogLineColumnizer columnizer) - { - //TODO this needs to be refactored - var directory = ConfigManager.Settings.Preferences.PortableMode ? ConfigManager.PortableModeDir : ConfigManager.ConfigDir; + public void ForceColumnizerForLoading (ILogLineColumnizer columnizer) + { + //TODO this needs to be refactored + var directory = ConfigManager.Settings.Preferences.PortableMode ? ConfigManager.PortableModeDir : ConfigManager.ConfigDir; - _forcedColumnizer = ColumnizerPicker.CloneColumnizer(columnizer, directory); - SetColumnizer(_forcedColumnizer); - } + _forcedColumnizerForLoading = ColumnizerPicker.CloneColumnizer(columnizer, directory); + } - public void ForceColumnizerForLoading(ILogLineColumnizer columnizer) - { - //TODO this needs to be refactored - var directory = ConfigManager.Settings.Preferences.PortableMode ? ConfigManager.PortableModeDir : ConfigManager.ConfigDir; + public void PreselectColumnizer (string columnizerName) + { + //TODO this needs to be refactored + var directory = ConfigManager.Settings.Preferences.PortableMode ? ConfigManager.PortableModeDir : ConfigManager.ConfigDir; - _forcedColumnizerForLoading = ColumnizerPicker.CloneColumnizer(columnizer, directory); - } + ILogLineColumnizer columnizer = ColumnizerPicker.FindColumnizerByName(columnizerName, PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers); + PreSelectColumnizer(ColumnizerPicker.CloneColumnizer(columnizer, directory)); + } - public void PreselectColumnizer(string columnizerName) - { - //TODO this needs to be refactored - var directory = ConfigManager.Settings.Preferences.PortableMode ? ConfigManager.PortableModeDir : ConfigManager.ConfigDir; + public void ColumnizerConfigChanged () + { + SetColumnizerInternal(CurrentColumnizer); + } - ILogLineColumnizer columnizer = ColumnizerPicker.FindColumnizerByName(columnizerName, PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers); - PreSelectColumnizer(ColumnizerPicker.CloneColumnizer(columnizer, directory)); - } + public void SetColumnizer (ILogLineColumnizer columnizer, BufferedDataGridView gridView) + { + PaintHelper.SetColumnizer(columnizer, gridView); + + gridView.Refresh(); + AutoResizeColumns(gridView); + ApplyFrozenState(gridView); + } - public void ColumnizerConfigChanged() + public IColumn GetCellValue (int rowIndex, int columnIndex) + { + if (columnIndex == 1) { - SetColumnizerInternal(CurrentColumnizer); + return new Column + { + FullValue = (rowIndex + 1).ToString() // line number + }; } - public void SetColumnizer(ILogLineColumnizer columnizer, BufferedDataGridView gridView) + if (columnIndex == 0) // marker column { - PaintHelper.SetColumnizer(columnizer, gridView); - - gridView.Refresh(); - AutoResizeColumns(gridView); - ApplyFrozenState(gridView); + return Column.EmptyColumn; } - public IColumn GetCellValue(int rowIndex, int columnIndex) + try { - if (columnIndex == 1) + IColumnizedLogLine cols = GetColumnsForLine(rowIndex); + if (cols != null && cols.ColumnValues != null) { - return new Column + if (columnIndex <= cols.ColumnValues.Length + 1) { - FullValue = (rowIndex + 1).ToString() // line number - }; - } - - if (columnIndex == 0) // marker column - { - return Column.EmptyColumn; - } + IColumn value = cols.ColumnValues[columnIndex - 2]; - try - { - IColumnizedLogLine cols = GetColumnsForLine(rowIndex); - if (cols != null && cols.ColumnValues != null) - { - if (columnIndex <= cols.ColumnValues.Length + 1) + if (value != null && value.DisplayValue != null) { - IColumn value = cols.ColumnValues[columnIndex - 2]; - - if (value != null && value.DisplayValue != null) - { - return value; - } return value; } + return value; + } - if (columnIndex == 2) - { - return cols.ColumnValues[^1]; - } - - return Column.EmptyColumn; + if (columnIndex == 2) + { + return cols.ColumnValues[^1]; } - } - catch - { + return Column.EmptyColumn; } - + } + catch + { return Column.EmptyColumn; } - public void CellPainting(BufferedDataGridView gridView, int rowIndex, DataGridViewCellPaintingEventArgs e) + return Column.EmptyColumn; + } + + public void CellPainting (BufferedDataGridView gridView, int rowIndex, DataGridViewCellPaintingEventArgs e) + { + if (rowIndex < 0 || e.ColumnIndex < 0) { - if (rowIndex < 0 || e.ColumnIndex < 0) - { - e.Handled = false; - return; - } + e.Handled = false; + return; + } - ILogLine line = _logFileReader.GetLogLineWithWait(rowIndex).Result; + ILogLine line = _logFileReader.GetLogLineWithWait(rowIndex).Result; - if (line != null) + if (line != null) + { + HighlightEntry entry = FindFirstNoWordMatchHilightEntry(line); + e.Graphics.SetClip(e.CellBounds); + + if ((e.State & DataGridViewElementStates.Selected) == DataGridViewElementStates.Selected) { - HighlightEntry entry = FindFirstNoWordMatchHilightEntry(line); - e.Graphics.SetClip(e.CellBounds); + Color backColor = ColorMode.BackgroundColor; - if ((e.State & DataGridViewElementStates.Selected) == DataGridViewElementStates.Selected) + Brush brush; + + if (gridView.Focused) + { + brush = new SolidBrush(e.CellStyle.SelectionBackColor); + } + else { - Color backColor = ColorMode.BackgroundColor; + Color color = backColor; + brush = new SolidBrush(color); + } - Brush brush; + e.Graphics.FillRectangle(brush, e.CellBounds); + brush.Dispose(); + } + else + { + Color bgColor = ColorMode.DockBackgroundColor; - if (gridView.Focused) - { - brush = new SolidBrush(e.CellStyle.SelectionBackColor); - } - else + if (!DebugOptions.DisableWordHighlight) + { + if (entry != null) { - Color color = backColor; - brush = new SolidBrush(color); + bgColor = entry.BackgroundColor; } - - e.Graphics.FillRectangle(brush, e.CellBounds); - brush.Dispose(); } else { - Color bgColor = ColorMode.DockBackgroundColor; - - if (!DebugOptions.DisableWordHighlight) - { - if (entry != null) - { - bgColor = entry.BackgroundColor; - } - } - else + if (entry != null) { - if (entry != null) - { - bgColor = entry.BackgroundColor; - } + bgColor = entry.BackgroundColor; } + } - e.CellStyle.BackColor = bgColor; + e.CellStyle.BackColor = bgColor; - e.PaintBackground(e.ClipBounds, false); - } + e.PaintBackground(e.ClipBounds, false); + } - if (DebugOptions.DisableWordHighlight) - { - e.PaintContent(e.CellBounds); - } - else - { - PaintCell(e, gridView, false, entry); - } + if (DebugOptions.DisableWordHighlight) + { + e.PaintContent(e.CellBounds); + } + else + { + PaintCell(e, gridView, false, entry); + } - if (e.ColumnIndex == 0) + if (e.ColumnIndex == 0) + { + if (_bookmarkProvider.IsBookmarkAtLine(rowIndex)) { - if (_bookmarkProvider.IsBookmarkAtLine(rowIndex)) + Rectangle r; // = new Rectangle(e.CellBounds.Left + 2, e.CellBounds.Top + 2, 6, 6); + r = e.CellBounds; + r.Inflate(-2, -2); + Brush brush = new SolidBrush(BookmarkColor); + e.Graphics.FillRectangle(brush, r); + brush.Dispose(); + Bookmark bookmark = _bookmarkProvider.GetBookmarkForLine(rowIndex); + + if (bookmark.Text.Length > 0) { - Rectangle r; // = new Rectangle(e.CellBounds.Left + 2, e.CellBounds.Top + 2, 6, 6); - r = e.CellBounds; - r.Inflate(-2, -2); - Brush brush = new SolidBrush(BookmarkColor); - e.Graphics.FillRectangle(brush, r); - brush.Dispose(); - Bookmark bookmark = _bookmarkProvider.GetBookmarkForLine(rowIndex); - - if (bookmark.Text.Length > 0) + StringFormat format = new() { - StringFormat format = new() - { - LineAlignment = StringAlignment.Center, - Alignment = StringAlignment.Center - }; - Brush brush2 = new SolidBrush(Color.FromArgb(255, 190, 100, 0)); - Font font = new("Courier New", Preferences.fontSize, FontStyle.Bold); - e.Graphics.DrawString("i", font, brush2, new RectangleF(r.Left, r.Top, r.Width, r.Height), - format); - font.Dispose(); - brush2.Dispose(); - } + LineAlignment = StringAlignment.Center, + Alignment = StringAlignment.Center + }; + Brush brush2 = new SolidBrush(Color.FromArgb(255, 190, 100, 0)); + Font font = new("Courier New", Preferences.fontSize, FontStyle.Bold); + e.Graphics.DrawString("i", font, brush2, new RectangleF(r.Left, r.Top, r.Width, r.Height), + format); + font.Dispose(); + brush2.Dispose(); } } - - e.Paint(e.CellBounds, DataGridViewPaintParts.Border); - e.Handled = true; } - } - public void OnDataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) - { - BufferedDataGridView gridView = (BufferedDataGridView)sender; - CellPainting(gridView, e.RowIndex, e); + e.Paint(e.CellBounds, DataGridViewPaintParts.Border); + e.Handled = true; } + } - /// - /// Returns the first HilightEntry that matches the given line - /// - /// - /// - /// - public HighlightEntry FindHighlightEntry(ITextValue line, bool noWordMatches) - { - // first check the temp entries - lock (_tempHighlightEntryListLock) + public void OnDataGridView_CellPainting (object sender, DataGridViewCellPaintingEventArgs e) + { + var gridView = (BufferedDataGridView)sender; + CellPainting(gridView, e.RowIndex, e); + } + + /// + /// Returns the first HilightEntry that matches the given line + /// + /// + /// + /// + public HighlightEntry FindHighlightEntry (ITextValue line, bool noWordMatches) + { + // first check the temp entries + lock (_tempHighlightEntryListLock) + { + foreach (HighlightEntry entry in _tempHighlightEntryList) { - foreach (HighlightEntry entry in _tempHighlightEntryList) + if (noWordMatches && entry.IsWordMatch) { - if (noWordMatches && entry.IsWordMatch) - { - continue; - } - if (CheckHighlightEntryMatch(entry, line)) - { - return entry; - } + continue; } - } - - lock (_currentHighlightGroupLock) - { - foreach (HighlightEntry entry in _currentHighlightGroup.HighlightEntryList) + if (CheckHighlightEntryMatch(entry, line)) { - if (noWordMatches && entry.IsWordMatch) - { - continue; - } - if (CheckHighlightEntryMatch(entry, line)) - { - return entry; - } + return entry; } - return null; } } - public IList FindHighlightMatches(ITextValue column) + lock (_currentHighlightGroupLock) { - IList resultList = new List(); - if (column != null) + foreach (HighlightEntry entry in _currentHighlightGroup.HighlightEntryList) { - lock (_currentHighlightGroupLock) + if (noWordMatches && entry.IsWordMatch) { - GetHighlightEntryMatches(column, _currentHighlightGroup.HighlightEntryList, resultList); + continue; } - lock (_tempHighlightEntryList) + if (CheckHighlightEntryMatch(entry, line)) { - GetHighlightEntryMatches(column, _tempHighlightEntryList, resultList); + return entry; } } - return resultList; + return null; } + } - public void FollowTailChanged(bool isChecked, bool byTrigger) + public IList FindHighlightMatches (ITextValue column) + { + IList resultList = new List(); + if (column != null) { - _guiStateArgs.FollowTail = isChecked; - - if (_guiStateArgs.FollowTail && _logFileReader != null) + lock (_currentHighlightGroupLock) { - if (dataGridView.RowCount >= _logFileReader.LineCount && _logFileReader.LineCount > 0) - { - dataGridView.FirstDisplayedScrollingRowIndex = _logFileReader.LineCount - 1; - } + GetHighlightEntryMatches(column, _currentHighlightGroup.HighlightEntryList, resultList); + } + lock (_tempHighlightEntryList) + { + GetHighlightEntryMatches(column, _tempHighlightEntryList, resultList); } - BeginInvoke(new MethodInvoker(dataGridView.Refresh)); - //this.dataGridView.Refresh(); - _parentLogTabWin.FollowTailChanged(this, isChecked, byTrigger); - SendGuiStateUpdate(); } + return resultList; + } - public void GotoLine(int line) + public void FollowTailChanged (bool isChecked, bool byTrigger) + { + _guiStateArgs.FollowTail = isChecked; + + if (_guiStateArgs.FollowTail && _logFileReader != null) { - if (line >= 0) + if (dataGridView.RowCount >= _logFileReader.LineCount && _logFileReader.LineCount > 0) { - if (line < dataGridView.RowCount) - { - SelectLine(line, false, true); - } - else - { - SelectLine(dataGridView.RowCount - 1, false, true); - } - dataGridView.Focus(); + dataGridView.FirstDisplayedScrollingRowIndex = _logFileReader.LineCount - 1; } } + BeginInvoke(new MethodInvoker(dataGridView.Refresh)); + //this.dataGridView.Refresh(); + _parentLogTabWin.FollowTailChanged(this, isChecked, byTrigger); + SendGuiStateUpdate(); + } - public void StartSearch() + public void GotoLine (int line) + { + if (line >= 0) { - _guiStateArgs.MenuEnabled = false; - GuiStateUpdate(this, _guiStateArgs); - SearchParams searchParams = _parentLogTabWin.SearchParams; - - if ((searchParams.IsForward || searchParams.IsFindNext) && !searchParams.IsShiftF3Pressed) + if (line < dataGridView.RowCount) { - searchParams.CurrentLine = dataGridView.CurrentCellAddress.Y + 1; + SelectLine(line, false, true); } else { - searchParams.CurrentLine = dataGridView.CurrentCellAddress.Y - 1; + SelectLine(dataGridView.RowCount - 1, false, true); } + dataGridView.Focus(); + } + } + + public void StartSearch () + { + _guiStateArgs.MenuEnabled = false; + GuiStateUpdate(this, _guiStateArgs); + SearchParams searchParams = _parentLogTabWin.SearchParams; + + if ((searchParams.IsForward || searchParams.IsFindNext) && !searchParams.IsShiftF3Pressed) + { + searchParams.CurrentLine = dataGridView.CurrentCellAddress.Y + 1; + } + else + { + searchParams.CurrentLine = dataGridView.CurrentCellAddress.Y - 1; + } - _currentSearchParams = searchParams; // remember for async "not found" messages + _currentSearchParams = searchParams; // remember for async "not found" messages - _isSearching = true; - _shouldCancel = false; - StatusLineText("Searching... Press ESC to cancel."); + _isSearching = true; + _shouldCancel = false; + StatusLineText("Searching... Press ESC to cancel."); - _progressEventArgs.MinValue = 0; - _progressEventArgs.MaxValue = dataGridView.RowCount; - _progressEventArgs.Value = 0; - _progressEventArgs.Visible = true; - SendProgressBarUpdate(); + _progressEventArgs.MinValue = 0; + _progressEventArgs.MaxValue = dataGridView.RowCount; + _progressEventArgs.Value = 0; + _progressEventArgs.Visible = true; + SendProgressBarUpdate(); - Task.Run(() => Search(searchParams)).ContinueWith(SearchComplete); + Task.Run(() => Search(searchParams)).ContinueWith(SearchComplete); - RemoveAllSearchHighlightEntries(); - AddSearchHitHighlightEntry(searchParams); + RemoveAllSearchHighlightEntries(); + AddSearchHitHighlightEntry(searchParams); + } + + private void SearchComplete (Task task) + { + if (Disposing) + { + return; } - private void SearchComplete(Task task) + try { - if (Disposing) + Invoke(new MethodInvoker(ResetProgressBar)); + var line = task.Result; + _guiStateArgs.MenuEnabled = true; + GuiStateUpdate(this, _guiStateArgs); + if (line == -1) { return; } - try + dataGridView.Invoke(new SelectLineFx((line1, triggerSyncCall) => SelectLine(line1, triggerSyncCall, true)), line, true); + } + catch (Exception ex) // in the case the windows is already destroyed + { + _logger.Warn(ex); + } + } + + public void SelectLogLine (int line) + { + Invoke(new SelectLineFx((line1, triggerSyncCall) => SelectLine(line1, triggerSyncCall, true)), line, true); + } + + public void SelectAndEnsureVisible (int line, bool triggerSyncCall) + { + try + { + SelectLine(line, triggerSyncCall, false); + + //if (!this.dataGridView.CurrentRow.Displayed) + if (line < dataGridView.FirstDisplayedScrollingRowIndex || line > dataGridView.FirstDisplayedScrollingRowIndex + dataGridView.DisplayedRowCount(false)) { - Invoke(new MethodInvoker(ResetProgressBar)); - int line = task.Result; - _guiStateArgs.MenuEnabled = true; - GuiStateUpdate(this, _guiStateArgs); - if (line == -1) + dataGridView.FirstDisplayedScrollingRowIndex = line; + for (var i = 0; i < 8 && dataGridView.FirstDisplayedScrollingRowIndex > 0 && line < dataGridView.FirstDisplayedScrollingRowIndex + dataGridView.DisplayedRowCount(false); ++i) { - return; + dataGridView.FirstDisplayedScrollingRowIndex -= 1; } - dataGridView.Invoke(new SelectLineFx((line1, triggerSyncCall) => SelectLine(line1, triggerSyncCall, true)), line, true); - } - catch (Exception ex) // in the case the windows is already destroyed - { - _logger.Warn(ex); + if (line >= dataGridView.FirstDisplayedScrollingRowIndex + dataGridView.DisplayedRowCount(false)) + { + dataGridView.FirstDisplayedScrollingRowIndex += 1; + } } + dataGridView.CurrentCell = dataGridView.Rows[line].Cells[0]; } - - public void SelectLogLine(int line) + catch (Exception e) { - Invoke(new SelectLineFx((line1, triggerSyncCall) => SelectLine(line1, triggerSyncCall, true)), line, true); + // In rare situations there seems to be an invalid argument exceptions (or something like this). Concrete location isn't visible in stack + // trace because use of Invoke(). So catch it, and log (better than crashing the app). + _logger.Error(e); } + } - public void SelectAndEnsureVisible(int line, bool triggerSyncCall) + public void OnLogWindowKeyDown (object sender, KeyEventArgs e) + { + if (_isErrorShowing) { - try - { - SelectLine(line, triggerSyncCall, false); + RemoveStatusLineError(); + } - //if (!this.dataGridView.CurrentRow.Displayed) - if (line < dataGridView.FirstDisplayedScrollingRowIndex || line > dataGridView.FirstDisplayedScrollingRowIndex + dataGridView.DisplayedRowCount(false)) + switch (e.KeyCode) + { + case Keys.F3 when _parentLogTabWin.SearchParams?.SearchText == null || _parentLogTabWin.SearchParams.SearchText.Length == 0: + { + return; + } + case Keys.F3: { - dataGridView.FirstDisplayedScrollingRowIndex = line; - for (int i = 0; i < 8 && dataGridView.FirstDisplayedScrollingRowIndex > 0 && line < dataGridView.FirstDisplayedScrollingRowIndex + dataGridView.DisplayedRowCount(false); ++i) + _parentLogTabWin.SearchParams.IsFindNext = true; + _parentLogTabWin.SearchParams.IsShiftF3Pressed = (e.Modifiers & Keys.Shift) == Keys.Shift; + StartSearch(); + break; + } + case Keys.Escape: + { + if (_isSearching) { - dataGridView.FirstDisplayedScrollingRowIndex -= 1; + _shouldCancel = true; } - if (line >= dataGridView.FirstDisplayedScrollingRowIndex + dataGridView.DisplayedRowCount(false)) - { - dataGridView.FirstDisplayedScrollingRowIndex += 1; - } + FireCancelHandlers(); + RemoveAllSearchHighlightEntries(); + break; } - dataGridView.CurrentCell = dataGridView.Rows[line].Cells[0]; - } - catch (Exception e) - { - // In rare situations there seems to be an invalid argument exceptions (or something like this). Concrete location isn't visible in stack - // trace because use of Invoke(). So catch it, and log (better than crashing the app). - _logger.Error(e); - } - } - - public void OnLogWindowKeyDown(object sender, KeyEventArgs e) - { - if (_isErrorShowing) - { - RemoveStatusLineError(); - } + case Keys.E when (e.Modifiers & Keys.Control) == Keys.Control: + { + StartEditMode(); - switch (e.KeyCode) - { - case Keys.F3 when _parentLogTabWin.SearchParams?.SearchText == null || _parentLogTabWin.SearchParams.SearchText.Length == 0: - { - return; - } - case Keys.F3: - { - _parentLogTabWin.SearchParams.IsFindNext = true; - _parentLogTabWin.SearchParams.IsShiftF3Pressed = (e.Modifiers & Keys.Shift) == Keys.Shift; - StartSearch(); - break; - } - case Keys.Escape: - { - if (_isSearching) - { - _shouldCancel = true; - } + break; + } + case Keys.Down when e.Modifiers == Keys.Alt: + { + var newLine = _logFileReader.GetNextMultiFileLine(dataGridView.CurrentCellAddress.Y); - FireCancelHandlers(); - RemoveAllSearchHighlightEntries(); - break; - } - case Keys.E when (e.Modifiers & Keys.Control) == Keys.Control: + if (newLine != -1) { - StartEditMode(); - - break; + SelectLine(newLine, false, true); } - case Keys.Down when e.Modifiers == Keys.Alt: - { - int newLine = _logFileReader.GetNextMultiFileLine(dataGridView.CurrentCellAddress.Y); - if (newLine != -1) - { - SelectLine(newLine, false, true); - } + e.Handled = true; - e.Handled = true; + break; + } + case Keys.Up when e.Modifiers == Keys.Alt: + { + var newLine = _logFileReader.GetPrevMultiFileLine(dataGridView.CurrentCellAddress.Y); - break; - } - case Keys.Up when e.Modifiers == Keys.Alt: + if (newLine != -1) { - int newLine = _logFileReader.GetPrevMultiFileLine(dataGridView.CurrentCellAddress.Y); + SelectLine(newLine - 1, false, true); + } - if (newLine != -1) - { - SelectLine(newLine - 1, false, true); - } + e.Handled = true; - e.Handled = true; + break; + } + case Keys.Enter when dataGridView.Focused: + { + ChangeRowHeight(e.Shift); + e.Handled = true; - break; - } - case Keys.Enter when dataGridView.Focused: - { - ChangeRowHeight(e.Shift); - e.Handled = true; + break; + } + case Keys.Back when dataGridView.Focused: + { + ChangeRowHeight(true); + e.Handled = true; - break; - } - case Keys.Back when dataGridView.Focused: - { - ChangeRowHeight(true); - e.Handled = true; + break; + } + case Keys.PageUp when e.Modifiers == Keys.Alt: + { + SelectPrevHighlightLine(); + e.Handled = true; - break; - } - case Keys.PageUp when e.Modifiers == Keys.Alt: - { - SelectPrevHighlightLine(); - e.Handled = true; + break; + } + case Keys.PageDown when e.Modifiers == Keys.Alt: + { + SelectNextHighlightLine(); + e.Handled = true; - break; - } - case Keys.PageDown when e.Modifiers == Keys.Alt: - { - SelectNextHighlightLine(); - e.Handled = true; + break; + } + case Keys.T when (e.Modifiers & Keys.Control) == Keys.Control && (e.Modifiers & Keys.Shift) == Keys.Shift: + { + FilterToTab(); + break; + } + } + } - break; - } - case Keys.T when (e.Modifiers & Keys.Control) == Keys.Control && (e.Modifiers & Keys.Shift) == Keys.Shift: - { - FilterToTab(); - break; - } - } + public void AddBookmarkOverlays () + { + const int OVERSCAN = 20; + + var firstLine = dataGridView.FirstDisplayedScrollingRowIndex; + if (firstLine < 0) + { + return; } - public void AddBookmarkOverlays() + firstLine -= OVERSCAN; + if (firstLine < 0) { - const int OVERSCAN = 20; + firstLine = 0; + } - int firstLine = dataGridView.FirstDisplayedScrollingRowIndex; - if (firstLine < 0) - { - return; - } + var oversizeCount = OVERSCAN; - firstLine -= OVERSCAN; - if (firstLine < 0) + for (var i = firstLine; i < dataGridView.RowCount; ++i) + { + if (!dataGridView.Rows[i].Displayed && i > dataGridView.FirstDisplayedScrollingRowIndex) { - firstLine = 0; + if (oversizeCount-- < 0) + { + break; + } } - - int oversizeCount = OVERSCAN; - - for (int i = firstLine; i < dataGridView.RowCount; ++i) + if (_bookmarkProvider.IsBookmarkAtLine(i)) { - if (!dataGridView.Rows[i].Displayed && i > dataGridView.FirstDisplayedScrollingRowIndex) + Bookmark bookmark = _bookmarkProvider.GetBookmarkForLine(i); + if (bookmark.Text.Length > 0) { - if (oversizeCount-- < 0) + //BookmarkOverlay overlay = new BookmarkOverlay(); + BookmarkOverlay overlay = bookmark.Overlay; + overlay.Bookmark = bookmark; + + Rectangle r; + if (dataGridView.Rows[i].Displayed) { - break; + r = dataGridView.GetCellDisplayRectangle(0, i, false); } - } - if (_bookmarkProvider.IsBookmarkAtLine(i)) - { - Bookmark bookmark = _bookmarkProvider.GetBookmarkForLine(i); - if (bookmark.Text.Length > 0) + else { - //BookmarkOverlay overlay = new BookmarkOverlay(); - BookmarkOverlay overlay = bookmark.Overlay; - overlay.Bookmark = bookmark; - - Rectangle r; - if (dataGridView.Rows[i].Displayed) + r = dataGridView.GetCellDisplayRectangle(0, dataGridView.FirstDisplayedScrollingRowIndex, false); + //int count = i - this.dataGridView.FirstDisplayedScrollingRowIndex; + var heightSum = 0; + if (dataGridView.FirstDisplayedScrollingRowIndex < i) { - r = dataGridView.GetCellDisplayRectangle(0, i, false); + for (var rn = dataGridView.FirstDisplayedScrollingRowIndex + 1; rn < i; ++rn) + { + //Rectangle rr = this.dataGridView.GetCellDisplayRectangle(0, rn, false); + //heightSum += rr.Height; + heightSum += GetRowHeight(rn); + } + r.Offset(0, r.Height + heightSum); } else { - r = dataGridView.GetCellDisplayRectangle(0, dataGridView.FirstDisplayedScrollingRowIndex, false); - //int count = i - this.dataGridView.FirstDisplayedScrollingRowIndex; - int heightSum = 0; - if (dataGridView.FirstDisplayedScrollingRowIndex < i) - { - for (int rn = dataGridView.FirstDisplayedScrollingRowIndex + 1; rn < i; ++rn) - { - //Rectangle rr = this.dataGridView.GetCellDisplayRectangle(0, rn, false); - //heightSum += rr.Height; - heightSum += GetRowHeight(rn); - } - r.Offset(0, r.Height + heightSum); - } - else + for (var rn = dataGridView.FirstDisplayedScrollingRowIndex + 1; rn > i; --rn) { - for (int rn = dataGridView.FirstDisplayedScrollingRowIndex + 1; rn > i; --rn) - { - //Rectangle rr = this.dataGridView.GetCellDisplayRectangle(0, rn, false); - //heightSum += rr.Height; - heightSum += GetRowHeight(rn); - } - r.Offset(0, -(r.Height + heightSum)); + //Rectangle rr = this.dataGridView.GetCellDisplayRectangle(0, rn, false); + //heightSum += rr.Height; + heightSum += GetRowHeight(rn); } - //r.Offset(0, this.dataGridView.DisplayRectangle.Height); + r.Offset(0, -(r.Height + heightSum)); } - if (_logger.IsDebugEnabled) - { - _logger.Debug("AddBookmarkOverlay() r.Location={0}, width={1}, scroll_offset={2}", r.Location.X, r.Width, dataGridView.HorizontalScrollingOffset); - } - overlay.Position = r.Location - new Size(dataGridView.HorizontalScrollingOffset, 0); - overlay.Position += new Size(10, r.Height / 2); - dataGridView.AddOverlay(overlay); + //r.Offset(0, this.dataGridView.DisplayRectangle.Height); + } + if (_logger.IsDebugEnabled) + { + _logger.Debug("AddBookmarkOverlay() r.Location={0}, width={1}, scroll_offset={2}", r.Location.X, r.Width, dataGridView.HorizontalScrollingOffset); } + overlay.Position = r.Location - new Size(dataGridView.HorizontalScrollingOffset, 0); + overlay.Position += new Size(10, r.Height / 2); + dataGridView.AddOverlay(overlay); } } } + } - public void ToggleBookmark() - { - BufferedDataGridView gridView; - int lineNum; + public void ToggleBookmark () + { + BufferedDataGridView gridView; + int lineNum; - if (filterGridView.Focused) + if (filterGridView.Focused) + { + gridView = filterGridView; + if (gridView.CurrentCellAddress.Y == -1) { - gridView = filterGridView; - if (gridView.CurrentCellAddress.Y == -1) - { - return; - } + return; + } - lineNum = _filterResultList[gridView.CurrentCellAddress.Y]; + lineNum = _filterResultList[gridView.CurrentCellAddress.Y]; + } + else + { + gridView = dataGridView; + if (gridView.CurrentCellAddress.Y == -1) + { + return; } - else + lineNum = dataGridView.CurrentCellAddress.Y; + } + + ToggleBookmark(lineNum); + } + + public void ToggleBookmark (int lineNum) + { + if (_bookmarkProvider.IsBookmarkAtLine(lineNum)) + { + Bookmark bookmark = _bookmarkProvider.GetBookmarkForLine(lineNum); + + if (string.IsNullOrEmpty(bookmark.Text) == false) { - gridView = dataGridView; - if (gridView.CurrentCellAddress.Y == -1) + if (DialogResult.No == MessageBox.Show("There's a comment attached to the bookmark. Really remove the bookmark?", "LogExpert", MessageBoxButtons.YesNo)) { return; } - lineNum = dataGridView.CurrentCellAddress.Y; } - - ToggleBookmark(lineNum); + _bookmarkProvider.RemoveBookmarkForLine(lineNum); + } + else + { + _bookmarkProvider.AddBookmark(new Bookmark(lineNum)); } + dataGridView.Refresh(); + filterGridView.Refresh(); + OnBookmarkAdded(); + } - public void ToggleBookmark(int lineNum) + public void SetBookmarkFromTrigger (int lineNum, string comment) + { + lock (_bookmarkLock) { - if (_bookmarkProvider.IsBookmarkAtLine(lineNum)) + ILogLine line = _logFileReader.GetLogLine(lineNum); + if (line == null) { - Bookmark bookmark = _bookmarkProvider.GetBookmarkForLine(lineNum); - - if (string.IsNullOrEmpty(bookmark.Text) == false) - { - if (DialogResult.No == MessageBox.Show("There's a comment attached to the bookmark. Really remove the bookmark?", "LogExpert", MessageBoxButtons.YesNo)) - { - return; - } - } - _bookmarkProvider.RemoveBookmarkForLine(lineNum); + return; } - else + var paramParser = new ParamParser(comment); + try { - _bookmarkProvider.AddBookmark(new Bookmark(lineNum)); + comment = paramParser.ReplaceParams(line, lineNum, FileName); } - dataGridView.Refresh(); - filterGridView.Refresh(); - OnBookmarkAdded(); - } - - public void SetBookmarkFromTrigger(int lineNum, string comment) - { - lock (_bookmarkLock) + catch (ArgumentException) { - ILogLine line = _logFileReader.GetLogLine(lineNum); - if (line == null) - { - return; - } - ParamParser paramParser = new ParamParser(comment); - try - { - comment = paramParser.ReplaceParams(line, lineNum, FileName); - } - catch (ArgumentException) - { - // occurs on invalid regex - } - if (_bookmarkProvider.IsBookmarkAtLine(lineNum)) - { - _bookmarkProvider.RemoveBookmarkForLine(lineNum); - } - _bookmarkProvider.AddBookmark(new Bookmark(lineNum, comment)); - OnBookmarkAdded(); + // occurs on invalid regex } + if (_bookmarkProvider.IsBookmarkAtLine(lineNum)) + { + _bookmarkProvider.RemoveBookmarkForLine(lineNum); + } + _bookmarkProvider.AddBookmark(new Bookmark(lineNum, comment)); + OnBookmarkAdded(); } + } - public void JumpNextBookmark() + public void JumpNextBookmark () + { + if (_bookmarkProvider.Bookmarks.Count > 0) { - if (_bookmarkProvider.Bookmarks.Count > 0) + if (filterGridView.Focused) { - if (filterGridView.Focused) + var index = FindNextBookmarkIndex(_filterResultList[filterGridView.CurrentCellAddress.Y]); + var startIndex = index; + var wrapped = false; + while (true) { - int index = FindNextBookmarkIndex(_filterResultList[filterGridView.CurrentCellAddress.Y]); - int startIndex = index; - bool wrapped = false; - while (true) + var lineNum = _bookmarkProvider.Bookmarks[index].LineNum; + if (_filterResultList.Contains(lineNum)) { - int lineNum = _bookmarkProvider.Bookmarks[index].LineNum; - if (_filterResultList.Contains(lineNum)) - { - int filterLine = _filterResultList.IndexOf(lineNum); - filterGridView.Rows[filterLine].Selected = true; - filterGridView.CurrentCell = filterGridView.Rows[filterLine].Cells[0]; - break; - } - index++; - if (index > _bookmarkProvider.Bookmarks.Count - 1) - { - index = 0; - wrapped = true; - } - if (index >= startIndex && wrapped) - { - break; - } + var filterLine = _filterResultList.IndexOf(lineNum); + filterGridView.Rows[filterLine].Selected = true; + filterGridView.CurrentCell = filterGridView.Rows[filterLine].Cells[0]; + break; } - } - else - { - int index = FindNextBookmarkIndex(dataGridView.CurrentCellAddress.Y); + index++; if (index > _bookmarkProvider.Bookmarks.Count - 1) { index = 0; + wrapped = true; + } + if (index >= startIndex && wrapped) + { + break; } - - int lineNum = _bookmarkProvider.Bookmarks[index].LineNum; - SelectLine(lineNum, true, true); } } + else + { + var index = FindNextBookmarkIndex(dataGridView.CurrentCellAddress.Y); + if (index > _bookmarkProvider.Bookmarks.Count - 1) + { + index = 0; + } + + var lineNum = _bookmarkProvider.Bookmarks[index].LineNum; + SelectLine(lineNum, true, true); + } } + } - public void JumpPrevBookmark() + public void JumpPrevBookmark () + { + if (_bookmarkProvider.Bookmarks.Count > 0) { - if (_bookmarkProvider.Bookmarks.Count > 0) + if (filterGridView.Focused) { - if (filterGridView.Focused) + //int index = this.bookmarkList.BinarySearch(this.filterResultList[this.filterGridView.CurrentCellAddress.Y]); + //if (index < 0) + // index = ~index; + //index--; + var index = FindPrevBookmarkIndex(_filterResultList[filterGridView.CurrentCellAddress.Y]); + if (index < 0) + { + index = _bookmarkProvider.Bookmarks.Count - 1; + } + var startIndex = index; + var wrapped = false; + while (true) { - //int index = this.bookmarkList.BinarySearch(this.filterResultList[this.filterGridView.CurrentCellAddress.Y]); - //if (index < 0) - // index = ~index; - //index--; - int index = FindPrevBookmarkIndex(_filterResultList[filterGridView.CurrentCellAddress.Y]); + var lineNum = _bookmarkProvider.Bookmarks[index].LineNum; + if (_filterResultList.Contains(lineNum)) + { + var filterLine = _filterResultList.IndexOf(lineNum); + filterGridView.Rows[filterLine].Selected = true; + filterGridView.CurrentCell = filterGridView.Rows[filterLine].Cells[0]; + break; + } + index--; if (index < 0) { index = _bookmarkProvider.Bookmarks.Count - 1; + wrapped = true; } - int startIndex = index; - bool wrapped = false; - while (true) + if (index <= startIndex && wrapped) { - int lineNum = _bookmarkProvider.Bookmarks[index].LineNum; - if (_filterResultList.Contains(lineNum)) - { - int filterLine = _filterResultList.IndexOf(lineNum); - filterGridView.Rows[filterLine].Selected = true; - filterGridView.CurrentCell = filterGridView.Rows[filterLine].Cells[0]; - break; - } - index--; - if (index < 0) - { - index = _bookmarkProvider.Bookmarks.Count - 1; - wrapped = true; - } - if (index <= startIndex && wrapped) - { - break; - } + break; } } - else + } + else + { + var index = FindPrevBookmarkIndex(dataGridView.CurrentCellAddress.Y); + if (index < 0) { - int index = FindPrevBookmarkIndex(dataGridView.CurrentCellAddress.Y); - if (index < 0) - { - index = _bookmarkProvider.Bookmarks.Count - 1; - } - - int lineNum = _bookmarkProvider.Bookmarks[index].LineNum; - SelectLine(lineNum, false, true); + index = _bookmarkProvider.Bookmarks.Count - 1; } + + var lineNum = _bookmarkProvider.Bookmarks[index].LineNum; + SelectLine(lineNum, false, true); } } + } - public void DeleteBookmarks(List lineNumList) + public void DeleteBookmarks (List lineNumList) + { + var bookmarksPresent = false; + foreach (var lineNum in lineNumList) { - bool bookmarksPresent = false; - foreach (int lineNum in lineNumList) + if (lineNum != -1) { - if (lineNum != -1) + if (_bookmarkProvider.IsBookmarkAtLine(lineNum) && + _bookmarkProvider.GetBookmarkForLine(lineNum).Text.Length > 0) { - if (_bookmarkProvider.IsBookmarkAtLine(lineNum) && - _bookmarkProvider.GetBookmarkForLine(lineNum).Text.Length > 0) - { - bookmarksPresent = true; - } + bookmarksPresent = true; } } - if (bookmarksPresent) + } + if (bookmarksPresent) + { + if ( + MessageBox.Show("There are some comments in the bookmarks. Really remove bookmarks?", "LogExpert", + MessageBoxButtons.YesNo) == DialogResult.No) { - if ( - MessageBox.Show("There are some comments in the bookmarks. Really remove bookmarks?", "LogExpert", - MessageBoxButtons.YesNo) == DialogResult.No) - { - return; - } + return; } - _bookmarkProvider.RemoveBookmarksForLines(lineNumList); - OnBookmarkRemoved(); } + _bookmarkProvider.RemoveBookmarksForLines(lineNumList); + OnBookmarkRemoved(); + } - public void SetTimeshiftValue(string value) + public void SetTimeshiftValue (string value) + { + _guiStateArgs.TimeshiftText = value; + if (CurrentColumnizer.IsTimeshiftImplemented()) { - _guiStateArgs.TimeshiftText = value; - if (CurrentColumnizer.IsTimeshiftImplemented()) + try { - try + if (_guiStateArgs.TimeshiftEnabled) { - if (_guiStateArgs.TimeshiftEnabled) + try { - try - { - string text = _guiStateArgs.TimeshiftText; - if (text.StartsWith("+")) - { - text = text.Substring(1); - } - TimeSpan timeSpan = TimeSpan.Parse(text); - int diff = (int)(timeSpan.Ticks / TimeSpan.TicksPerMillisecond); - CurrentColumnizer.SetTimeOffset(diff); - } - catch (Exception) + var text = _guiStateArgs.TimeshiftText; + if (text.StartsWith("+")) { - CurrentColumnizer.SetTimeOffset(0); + text = text.Substring(1); } + var timeSpan = TimeSpan.Parse(text); + var diff = (int)(timeSpan.Ticks / TimeSpan.TicksPerMillisecond); + CurrentColumnizer.SetTimeOffset(diff); } - else + catch (Exception) { CurrentColumnizer.SetTimeOffset(0); } - dataGridView.Refresh(); - filterGridView.Refresh(); - if (CurrentColumnizer.IsTimeshiftImplemented()) - { - SetTimestampLimits(); - SyncTimestampDisplay(); - } } - catch (FormatException ex) + else { - _logger.Error(ex); + CurrentColumnizer.SetTimeOffset(0); + } + dataGridView.Refresh(); + filterGridView.Refresh(); + if (CurrentColumnizer.IsTimeshiftImplemented()) + { + SetTimestampLimits(); + SyncTimestampDisplay(); } } - } - - public void ToggleFilterPanel() - { - splitContainerLogWindow.Panel2Collapsed = !splitContainerLogWindow.Panel2Collapsed; - if (!splitContainerLogWindow.Panel2Collapsed) - { - filterComboBox.Focus(); - } - else + catch (FormatException ex) { - dataGridView.Focus(); + _logger.Error(ex); } } + } - public void LogWindowActivated() + public void ToggleFilterPanel () + { + splitContainerLogWindow.Panel2Collapsed = !splitContainerLogWindow.Panel2Collapsed; + if (!splitContainerLogWindow.Panel2Collapsed) + { + filterComboBox.Focus(); + } + else { - if (_guiStateArgs.FollowTail && !_isDeadFile) - { - OnTailFollowed(EventArgs.Empty); - } - if (Preferences.timestampControl) - { - SetTimestampLimits(); - SyncTimestampDisplay(); - } dataGridView.Focus(); - - SendGuiStateUpdate(); - SendStatusLineUpdate(); - SendProgressBarUpdate(); } + } - public void SetCellSelectionMode(bool isCellMode) + public void LogWindowActivated () + { + if (_guiStateArgs.FollowTail && !_isDeadFile) { - if (isCellMode) - { - //possible performance issue, see => https://docs.microsoft.com/en-us/dotnet/desktop/winforms/controls/best-practices-for-scaling-the-windows-forms-datagridview-control?view=netframeworkdesktop-4.8#using-the-selected-cells-rows-and-columns-collections-efficiently - dataGridView.SelectionMode = DataGridViewSelectionMode.CellSelect; - } - else - { - dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect; - } - - _guiStateArgs.CellSelectMode = isCellMode; + OnTailFollowed(EventArgs.Empty); } - - public void TimeshiftEnabled(bool isEnabled, string shiftValue) + if (Preferences.timestampControl) { - _guiStateArgs.TimeshiftEnabled = isEnabled; SetTimestampLimits(); - SetTimeshiftValue(shiftValue); + SyncTimestampDisplay(); + } + dataGridView.Focus(); + + SendGuiStateUpdate(); + SendStatusLineUpdate(); + SendProgressBarUpdate(); + } + + public void SetCellSelectionMode (bool isCellMode) + { + if (isCellMode) + { + //possible performance issue, see => https://docs.microsoft.com/en-us/dotnet/desktop/winforms/controls/best-practices-for-scaling-the-windows-forms-datagridview-control?view=netframeworkdesktop-4.8#using-the-selected-cells-rows-and-columns-collections-efficiently + dataGridView.SelectionMode = DataGridViewSelectionMode.CellSelect; + } + else + { + dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect; } - public void CopyMarkedLinesToTab() + _guiStateArgs.CellSelectMode = isCellMode; + } + + public void TimeshiftEnabled (bool isEnabled, string shiftValue) + { + _guiStateArgs.TimeshiftEnabled = isEnabled; + SetTimestampLimits(); + SetTimeshiftValue(shiftValue); + } + + public void CopyMarkedLinesToTab () + { + if (dataGridView.SelectionMode == DataGridViewSelectionMode.FullRowSelect) { - if (dataGridView.SelectionMode == DataGridViewSelectionMode.FullRowSelect) + var lineNumList = new List(); + foreach (DataGridViewRow row in dataGridView.SelectedRows) { - List lineNumList = new List(); - foreach (DataGridViewRow row in dataGridView.SelectedRows) + if (row.Index != -1) { - if (row.Index != -1) - { - lineNumList.Add(row.Index); - } + lineNumList.Add(row.Index); } - lineNumList.Sort(); - // create dummy FilterPipe for connecting line numbers to original window - // setting IsStopped to true prevents further filter processing - FilterPipe pipe = new FilterPipe(new FilterParams(), this) - { - IsStopped = true - }; - WritePipeToTab(pipe, lineNumList, Text + "->C", null); } - else + lineNumList.Sort(); + // create dummy FilterPipe for connecting line numbers to original window + // setting IsStopped to true prevents further filter processing + var pipe = new FilterPipe(new FilterParams(), this) { - string fileName = Path.GetTempFileName(); - FileStream fStream = new FileStream(fileName, FileMode.Append, FileAccess.Write, FileShare.Read); - StreamWriter writer = new StreamWriter(fStream, Encoding.Unicode); + IsStopped = true + }; + WritePipeToTab(pipe, lineNumList, Text + "->C", null); + } + else + { + var fileName = Path.GetTempFileName(); + var fStream = new FileStream(fileName, FileMode.Append, FileAccess.Write, FileShare.Read); + var writer = new StreamWriter(fStream, Encoding.Unicode); - DataObject data = dataGridView.GetClipboardContent(); - string text = data.GetText(TextDataFormat.Text); - writer.Write(text); + DataObject data = dataGridView.GetClipboardContent(); + var text = data.GetText(TextDataFormat.Text); + writer.Write(text); - writer.Close(); - string title = Util.GetNameFromPath(FileName) + "->Clip"; - _parentLogTabWin.AddTempFileTab(fileName, title); - } + writer.Close(); + var title = Util.GetNameFromPath(FileName) + "->Clip"; + _parentLogTabWin.AddTempFileTab(fileName, title); } + } - /// - /// Change the file encoding. May force a reload if byte count ot preamble lenght differs from previous used encoding. - /// - /// - public void ChangeEncoding(Encoding encoding) + /// + /// Change the file encoding. May force a reload if byte count ot preamble lenght differs from previous used encoding. + /// + /// + public void ChangeEncoding (Encoding encoding) + { + _logFileReader.ChangeEncoding(encoding); + EncodingOptions.Encoding = encoding; + if (_guiStateArgs.CurrentEncoding.IsSingleByte != encoding.IsSingleByte || + _guiStateArgs.CurrentEncoding.GetPreamble().Length != encoding.GetPreamble().Length) { - _logFileReader.ChangeEncoding(encoding); - EncodingOptions.Encoding = encoding; - if (_guiStateArgs.CurrentEncoding.IsSingleByte != encoding.IsSingleByte || - _guiStateArgs.CurrentEncoding.GetPreamble().Length != encoding.GetPreamble().Length) - { - Reload(); - } - else - { - dataGridView.Refresh(); - SendGuiStateUpdate(); - } - _guiStateArgs.CurrentEncoding = _logFileReader.CurrentEncoding; + Reload(); } - - public void Reload() + else { - SavePersistenceData(false); + dataGridView.Refresh(); + SendGuiStateUpdate(); + } + _guiStateArgs.CurrentEncoding = _logFileReader.CurrentEncoding; + } - _reloadMemento = new ReloadMemento - { - CurrentLine = dataGridView.CurrentCellAddress.Y, - FirstDisplayedLine = dataGridView.FirstDisplayedScrollingRowIndex - }; - _forcedColumnizerForLoading = CurrentColumnizer; + public void Reload () + { + SavePersistenceData(false); - if (_fileNames == null || !IsMultiFile) - { - LoadFile(FileName, EncodingOptions); - } - else - { - LoadFilesAsMulti(_fileNames, EncodingOptions); - } - //if (currentLine < this.dataGridView.RowCount && currentLine >= 0) - // this.dataGridView.CurrentCell = this.dataGridView.Rows[currentLine].Cells[0]; - //if (firstDisplayedLine < this.dataGridView.RowCount && firstDisplayedLine >= 0) - // this.dataGridView.FirstDisplayedScrollingRowIndex = firstDisplayedLine; + _reloadMemento = new ReloadMemento + { + CurrentLine = dataGridView.CurrentCellAddress.Y, + FirstDisplayedLine = dataGridView.FirstDisplayedScrollingRowIndex + }; + _forcedColumnizerForLoading = CurrentColumnizer; - //if (this.filterTailCheckBox.Checked) - //{ - // _logger.logInfo("Refreshing filter view because of reload."); - // FilterSearch(); - //} + if (_fileNames == null || !IsMultiFile) + { + LoadFile(FileName, EncodingOptions); } - - public void PreferencesChanged(Preferences newPreferences, bool isLoadTime, SettingsFlags flags) + else { - if ((flags & SettingsFlags.GuiOrColors) == SettingsFlags.GuiOrColors) - { - NormalFont = new Font(new FontFamily(newPreferences.fontName), newPreferences.fontSize); - BoldFont = new Font(NormalFont, FontStyle.Bold); - MonospacedFont = new Font("Courier New", Preferences.fontSize, FontStyle.Bold); - - int lineSpacing = NormalFont.FontFamily.GetLineSpacing(FontStyle.Regular); - float lineSpacingPixel = NormalFont.Size * lineSpacing / NormalFont.FontFamily.GetEmHeight(FontStyle.Regular); + LoadFilesAsMulti(_fileNames, EncodingOptions); + } + //if (currentLine < this.dataGridView.RowCount && currentLine >= 0) + // this.dataGridView.CurrentCell = this.dataGridView.Rows[currentLine].Cells[0]; + //if (firstDisplayedLine < this.dataGridView.RowCount && firstDisplayedLine >= 0) + // this.dataGridView.FirstDisplayedScrollingRowIndex = firstDisplayedLine; - dataGridView.DefaultCellStyle.Font = NormalFont; - filterGridView.DefaultCellStyle.Font = NormalFont; - _lineHeight = NormalFont.Height + 4; - dataGridView.RowTemplate.Height = NormalFont.Height + 4; + //if (this.filterTailCheckBox.Checked) + //{ + // _logger.logInfo("Refreshing filter view because of reload."); + // FilterSearch(); + //} + } - ShowBookmarkBubbles = Preferences.showBubbles; + public void PreferencesChanged (Preferences newPreferences, bool isLoadTime, SettingsFlags flags) + { + if ((flags & SettingsFlags.GuiOrColors) == SettingsFlags.GuiOrColors) + { + NormalFont = new Font(new FontFamily(newPreferences.fontName), newPreferences.fontSize); + BoldFont = new Font(NormalFont, FontStyle.Bold); + MonospacedFont = new Font("Courier New", Preferences.fontSize, FontStyle.Bold); - ApplyDataGridViewPrefs(dataGridView, newPreferences); - ApplyDataGridViewPrefs(filterGridView, newPreferences); + var lineSpacing = NormalFont.FontFamily.GetLineSpacing(FontStyle.Regular); + var lineSpacingPixel = NormalFont.Size * lineSpacing / NormalFont.FontFamily.GetEmHeight(FontStyle.Regular); - if (Preferences.timestampControl) - { - SetTimestampLimits(); - SyncTimestampDisplay(); - } - if (isLoadTime) - { - filterTailCheckBox.Checked = Preferences.filterTail; - syncFilterCheckBox.Checked = Preferences.filterSync; - //this.FollowTailChanged(this.Preferences.followTail, false); - } + dataGridView.DefaultCellStyle.Font = NormalFont; + filterGridView.DefaultCellStyle.Font = NormalFont; + _lineHeight = NormalFont.Height + 4; + dataGridView.RowTemplate.Height = NormalFont.Height + 4; - _timeSpreadCalc.TimeMode = Preferences.timeSpreadTimeMode; - timeSpreadingControl.ForeColor = Preferences.timeSpreadColor; - timeSpreadingControl.ReverseAlpha = Preferences.reverseAlpha; - if (CurrentColumnizer.IsTimeshiftImplemented()) - { - timeSpreadingControl.Invoke(new MethodInvoker(timeSpreadingControl.Refresh)); - ShowTimeSpread(Preferences.showTimeSpread); - } - ToggleColumnFinder(Preferences.showColumnFinder, false); - } + ShowBookmarkBubbles = Preferences.showBubbles; - if ((flags & SettingsFlags.FilterList) == SettingsFlags.FilterList) + ApplyDataGridViewPrefs(dataGridView, newPreferences); + ApplyDataGridViewPrefs(filterGridView, newPreferences); + + if (Preferences.timestampControl) + { + SetTimestampLimits(); + SyncTimestampDisplay(); + } + if (isLoadTime) { - HandleChangedFilterList(); + filterTailCheckBox.Checked = Preferences.filterTail; + syncFilterCheckBox.Checked = Preferences.filterSync; + //this.FollowTailChanged(this.Preferences.followTail, false); } - if ((flags & SettingsFlags.FilterHistory) == SettingsFlags.FilterHistory) + _timeSpreadCalc.TimeMode = Preferences.timeSpreadTimeMode; + timeSpreadingControl.ForeColor = Preferences.timeSpreadColor; + timeSpreadingControl.ReverseAlpha = Preferences.reverseAlpha; + if (CurrentColumnizer.IsTimeshiftImplemented()) { - UpdateFilterHistoryFromSettings(); - - if (isLoadTime) - { - AutoResizeFilterBox(); - } + timeSpreadingControl.Invoke(new MethodInvoker(timeSpreadingControl.Refresh)); + ShowTimeSpread(Preferences.showTimeSpread); } + ToggleColumnFinder(Preferences.showColumnFinder, false); + } + + if ((flags & SettingsFlags.FilterList) == SettingsFlags.FilterList) + { + HandleChangedFilterList(); } - public bool ScrollToTimestamp(DateTime timestamp, bool roundToSeconds, bool triggerSyncCall) + if ((flags & SettingsFlags.FilterHistory) == SettingsFlags.FilterHistory) { - if (InvokeRequired) + UpdateFilterHistoryFromSettings(); + + if (isLoadTime) { - BeginInvoke(new ScrollToTimestampFx(ScrollToTimestampWorker), timestamp, roundToSeconds, triggerSyncCall); - return true; + AutoResizeFilterBox(); } + } + } + + public bool ScrollToTimestamp (DateTime timestamp, bool roundToSeconds, bool triggerSyncCall) + { + if (InvokeRequired) + { + BeginInvoke(new ScrollToTimestampFx(ScrollToTimestampWorker), timestamp, roundToSeconds, triggerSyncCall); + return true; + } - return ScrollToTimestampWorker(timestamp, roundToSeconds, triggerSyncCall); + return ScrollToTimestampWorker(timestamp, roundToSeconds, triggerSyncCall); + } + + public bool ScrollToTimestampWorker (DateTime timestamp, bool roundToSeconds, bool triggerSyncCall) + { + var hasScrolled = false; + if (!CurrentColumnizer.IsTimeshiftImplemented() || dataGridView.RowCount == 0) + { + return false; } - public bool ScrollToTimestampWorker(DateTime timestamp, bool roundToSeconds, bool triggerSyncCall) + //this.Cursor = Cursors.WaitCursor; + var currentLine = dataGridView.CurrentCellAddress.Y; + if (currentLine < 0 || currentLine >= dataGridView.RowCount) { - bool hasScrolled = false; - if (!CurrentColumnizer.IsTimeshiftImplemented() || dataGridView.RowCount == 0) - { - return false; - } + currentLine = 0; + } + var foundLine = FindTimestampLine(currentLine, timestamp, roundToSeconds); + if (foundLine >= 0) + { + SelectAndEnsureVisible(foundLine, triggerSyncCall); + hasScrolled = true; + } + //this.Cursor = Cursors.Default; + return hasScrolled; + } - //this.Cursor = Cursors.WaitCursor; - int currentLine = dataGridView.CurrentCellAddress.Y; - if (currentLine < 0 || currentLine >= dataGridView.RowCount) + public int FindTimestampLine (int lineNum, DateTime timestamp, bool roundToSeconds) + { + var foundLine = + FindTimestampLine_Internal(lineNum, 0, dataGridView.RowCount - 1, timestamp, roundToSeconds); + if (foundLine >= 0) + { + // go backwards to the first occurence of the hit + DateTime foundTimestamp = GetTimestampForLine(ref foundLine, roundToSeconds); + while (foundTimestamp.CompareTo(timestamp) == 0 && foundLine >= 0) { - currentLine = 0; + foundLine--; + foundTimestamp = GetTimestampForLine(ref foundLine, roundToSeconds); } - int foundLine = FindTimestampLine(currentLine, timestamp, roundToSeconds); - if (foundLine >= 0) + if (foundLine < 0) { - SelectAndEnsureVisible(foundLine, triggerSyncCall); - hasScrolled = true; + return 0; } - //this.Cursor = Cursors.Default; - return hasScrolled; + + foundLine++; + GetTimestampForLineForward(ref foundLine, roundToSeconds); // fwd to next valid timestamp + return foundLine; } + return -foundLine; + } - public int FindTimestampLine(int lineNum, DateTime timestamp, bool roundToSeconds) + public int FindTimestampLine_Internal (int lineNum, int rangeStart, int rangeEnd, DateTime timestamp, + bool roundToSeconds) + { + _logger.Debug("FindTimestampLine_Internal(): timestamp={0}, lineNum={1}, rangeStart={2}, rangeEnd={3}", timestamp, lineNum, rangeStart, rangeEnd); + var refLine = lineNum; + DateTime currentTimestamp = GetTimestampForLine(ref refLine, roundToSeconds); + if (currentTimestamp.CompareTo(timestamp) == 0) { - int foundLine = - FindTimestampLine_Internal(lineNum, 0, dataGridView.RowCount - 1, timestamp, roundToSeconds); - if (foundLine >= 0) - { - // go backwards to the first occurence of the hit - DateTime foundTimestamp = GetTimestampForLine(ref foundLine, roundToSeconds); - while (foundTimestamp.CompareTo(timestamp) == 0 && foundLine >= 0) - { - foundLine--; - foundTimestamp = GetTimestampForLine(ref foundLine, roundToSeconds); - } - if (foundLine < 0) - { - return 0; - } + return lineNum; + } + if (timestamp < currentTimestamp) + { + //rangeStart = rangeStart; + rangeEnd = lineNum; + } + else + { + rangeStart = lineNum; + //rangeEnd = rangeEnd; + } - foundLine++; - GetTimestampForLineForward(ref foundLine, roundToSeconds); // fwd to next valid timestamp - return foundLine; - } - return -foundLine; + if (rangeEnd - rangeStart <= 0) + { + return -lineNum; } - public int FindTimestampLine_Internal(int lineNum, int rangeStart, int rangeEnd, DateTime timestamp, - bool roundToSeconds) + lineNum = (rangeEnd - rangeStart) / 2 + rangeStart; + // prevent endless loop + if (rangeEnd - rangeStart < 2) { - _logger.Debug("FindTimestampLine_Internal(): timestamp={0}, lineNum={1}, rangeStart={2}, rangeEnd={3}", timestamp, lineNum, rangeStart, rangeEnd); - int refLine = lineNum; - DateTime currentTimestamp = GetTimestampForLine(ref refLine, roundToSeconds); + currentTimestamp = GetTimestampForLine(ref rangeStart, roundToSeconds); if (currentTimestamp.CompareTo(timestamp) == 0) { - return lineNum; - } - if (timestamp < currentTimestamp) - { - //rangeStart = rangeStart; - rangeEnd = lineNum; - } - else - { - rangeStart = lineNum; - //rangeEnd = rangeEnd; + return rangeStart; } - - if (rangeEnd - rangeStart <= 0) - { - return -lineNum; - } - - lineNum = (rangeEnd - rangeStart) / 2 + rangeStart; - // prevent endless loop - if (rangeEnd - rangeStart < 2) + currentTimestamp = GetTimestampForLine(ref rangeEnd, roundToSeconds); + if (currentTimestamp.CompareTo(timestamp) == 0) { - currentTimestamp = GetTimestampForLine(ref rangeStart, roundToSeconds); - if (currentTimestamp.CompareTo(timestamp) == 0) - { - return rangeStart; - } - currentTimestamp = GetTimestampForLine(ref rangeEnd, roundToSeconds); - if (currentTimestamp.CompareTo(timestamp) == 0) - { - return rangeEnd; - } - return -lineNum; + return rangeEnd; } - - return FindTimestampLine_Internal(lineNum, rangeStart, rangeEnd, timestamp, roundToSeconds); + return -lineNum; } - /** - * Get the timestamp for the given line number. If the line - * has no timestamp, the previous line will be checked until a - * timestamp is found. - */ + return FindTimestampLine_Internal(lineNum, rangeStart, rangeEnd, timestamp, roundToSeconds); + } + + /** + * Get the timestamp for the given line number. If the line + * has no timestamp, the previous line will be checked until a + * timestamp is found. + */ - public DateTime GetTimestampForLine(ref int lineNum, bool roundToSeconds) + public DateTime GetTimestampForLine (ref int lineNum, bool roundToSeconds) + { + lock (_currentColumnizerLock) { - lock (_currentColumnizerLock) + if (!CurrentColumnizer.IsTimeshiftImplemented()) { - if (!CurrentColumnizer.IsTimeshiftImplemented()) - { - return DateTime.MinValue; - } - _logger.Debug("GetTimestampForLine({0}) enter", lineNum); - DateTime timeStamp = DateTime.MinValue; - bool lookBack = false; - if (lineNum >= 0 && lineNum < dataGridView.RowCount) + return DateTime.MinValue; + } + _logger.Debug("GetTimestampForLine({0}) enter", lineNum); + DateTime timeStamp = DateTime.MinValue; + var lookBack = false; + if (lineNum >= 0 && lineNum < dataGridView.RowCount) + { + while (timeStamp.CompareTo(DateTime.MinValue) == 0 && lineNum >= 0) { - while (timeStamp.CompareTo(DateTime.MinValue) == 0 && lineNum >= 0) + if (_isTimestampDisplaySyncing && _shouldTimestampDisplaySyncingCancel) { - if (_isTimestampDisplaySyncing && _shouldTimestampDisplaySyncingCancel) - { - return DateTime.MinValue; - } - lookBack = true; - ILogLine logLine = _logFileReader.GetLogLine(lineNum); - if (logLine == null) - { - return DateTime.MinValue; - } - ColumnizerCallbackObject.LineNum = lineNum; - timeStamp = CurrentColumnizer.GetTimestamp(ColumnizerCallbackObject, logLine); - if (roundToSeconds) - { - timeStamp = timeStamp.Subtract(TimeSpan.FromMilliseconds(timeStamp.Millisecond)); - } - lineNum--; + return DateTime.MinValue; } + lookBack = true; + ILogLine logLine = _logFileReader.GetLogLine(lineNum); + if (logLine == null) + { + return DateTime.MinValue; + } + ColumnizerCallbackObject.LineNum = lineNum; + timeStamp = CurrentColumnizer.GetTimestamp(ColumnizerCallbackObject, logLine); + if (roundToSeconds) + { + timeStamp = timeStamp.Subtract(TimeSpan.FromMilliseconds(timeStamp.Millisecond)); + } + lineNum--; } - if (lookBack) - { - lineNum++; - } - _logger.Debug("GetTimestampForLine() leave with lineNum={0}", lineNum); - return timeStamp; } + if (lookBack) + { + lineNum++; + } + _logger.Debug("GetTimestampForLine() leave with lineNum={0}", lineNum); + return timeStamp; } + } - /** - * Get the timestamp for the given line number. If the line - * has no timestamp, the next line will be checked until a - * timestamp is found. - */ + /** + * Get the timestamp for the given line number. If the line + * has no timestamp, the next line will be checked until a + * timestamp is found. + */ - public DateTime GetTimestampForLineForward(ref int lineNum, bool roundToSeconds) + public DateTime GetTimestampForLineForward (ref int lineNum, bool roundToSeconds) + { + lock (_currentColumnizerLock) { - lock (_currentColumnizerLock) + if (!CurrentColumnizer.IsTimeshiftImplemented()) { - if (!CurrentColumnizer.IsTimeshiftImplemented()) - { - return DateTime.MinValue; - } + return DateTime.MinValue; + } - DateTime timeStamp = DateTime.MinValue; - bool lookFwd = false; - if (lineNum >= 0 && lineNum < dataGridView.RowCount) + DateTime timeStamp = DateTime.MinValue; + var lookFwd = false; + if (lineNum >= 0 && lineNum < dataGridView.RowCount) + { + while (timeStamp.CompareTo(DateTime.MinValue) == 0 && lineNum < dataGridView.RowCount) { - while (timeStamp.CompareTo(DateTime.MinValue) == 0 && lineNum < dataGridView.RowCount) + lookFwd = true; + ILogLine logLine = _logFileReader.GetLogLine(lineNum); + if (logLine == null) { - lookFwd = true; - ILogLine logLine = _logFileReader.GetLogLine(lineNum); - if (logLine == null) - { - timeStamp = DateTime.MinValue; - break; - } - timeStamp = CurrentColumnizer.GetTimestamp(ColumnizerCallbackObject, logLine); - if (roundToSeconds) - { - timeStamp = timeStamp.Subtract(TimeSpan.FromMilliseconds(timeStamp.Millisecond)); - } - lineNum++; + timeStamp = DateTime.MinValue; + break; } + timeStamp = CurrentColumnizer.GetTimestamp(ColumnizerCallbackObject, logLine); + if (roundToSeconds) + { + timeStamp = timeStamp.Subtract(TimeSpan.FromMilliseconds(timeStamp.Millisecond)); + } + lineNum++; } - if (lookFwd) - { - lineNum--; - } - return timeStamp; } + if (lookFwd) + { + lineNum--; + } + return timeStamp; } + } - public void AppFocusLost() - { - InvalidateCurrentRow(dataGridView); - } + public void AppFocusLost () + { + InvalidateCurrentRow(dataGridView); + } - public void AppFocusGained() - { - InvalidateCurrentRow(dataGridView); - } + public void AppFocusGained () + { + InvalidateCurrentRow(dataGridView); + } - public ILogLine GetCurrentLine() + public ILogLine GetCurrentLine () + { + if (dataGridView.CurrentRow != null && dataGridView.CurrentRow.Index != -1) { - if (dataGridView.CurrentRow != null && dataGridView.CurrentRow.Index != -1) - { - return _logFileReader.GetLogLine(dataGridView.CurrentRow.Index); - } - return null; + return _logFileReader.GetLogLine(dataGridView.CurrentRow.Index); } + return null; + } - public ILogLine GetLine(int lineNum) + public ILogLine GetLine (int lineNum) + { + if (lineNum < 0 || _logFileReader == null || lineNum >= _logFileReader.LineCount) { - if (lineNum < 0 || _logFileReader == null || lineNum >= _logFileReader.LineCount) - { - return null; - } - return _logFileReader.GetLogLine(lineNum); + return null; } + return _logFileReader.GetLogLine(lineNum); + } - public int GetCurrentLineNum() + public int GetCurrentLineNum () + { + if (dataGridView.CurrentRow == null) { - if (dataGridView.CurrentRow == null) - { - return -1; - } - return dataGridView.CurrentRow.Index; + return -1; } + return dataGridView.CurrentRow.Index; + } - public int GetRealLineNum() + public int GetRealLineNum () + { + var lineNum = GetCurrentLineNum(); + if (lineNum == -1) { - int lineNum = GetCurrentLineNum(); - if (lineNum == -1) - { - return -1; - } - return _logFileReader.GetRealLineNumForVirtualLineNum(lineNum); + return -1; } + return _logFileReader.GetRealLineNumForVirtualLineNum(lineNum); + } - public ILogFileInfo GetCurrentFileInfo() + public ILogFileInfo GetCurrentFileInfo () + { + if (dataGridView.CurrentRow != null && dataGridView.CurrentRow.Index != -1) { - if (dataGridView.CurrentRow != null && dataGridView.CurrentRow.Index != -1) - { - return _logFileReader.GetLogFileInfoForLine(dataGridView.CurrentRow.Index); - } - return null; + return _logFileReader.GetLogFileInfoForLine(dataGridView.CurrentRow.Index); } + return null; + } - /// - /// zero-based - /// - /// - /// - public string GetCurrentFileName(int lineNum) - { - return _logFileReader.GetLogFileNameForLine(lineNum); - } + /// + /// zero-based + /// + /// + /// + public string GetCurrentFileName (int lineNum) + { + return _logFileReader.GetLogFileNameForLine(lineNum); + } - // =============== end of bookmark stuff =================================== + // =============== end of bookmark stuff =================================== - public void ShowLineColumn(bool show) - { - dataGridView.Columns[1].Visible = show; - filterGridView.Columns[1].Visible = show; - } + public void ShowLineColumn (bool show) + { + dataGridView.Columns[1].Visible = show; + filterGridView.Columns[1].Visible = show; + } - // ================================================================= - // Pattern statistics - // ================================================================= + // ================================================================= + // Pattern statistics + // ================================================================= - public void PatternStatistic() - { - InitPatternWindow(); - } + public void PatternStatistic () + { + InitPatternWindow(); + } - public void PatternStatisticSelectRange(PatternArgs patternArgs) + public void PatternStatisticSelectRange (PatternArgs patternArgs) + { + if (dataGridView.SelectionMode == DataGridViewSelectionMode.FullRowSelect) { - if (dataGridView.SelectionMode == DataGridViewSelectionMode.FullRowSelect) + List lineNumList = []; + foreach (DataGridViewRow row in dataGridView.SelectedRows) { - List lineNumList = []; - foreach (DataGridViewRow row in dataGridView.SelectedRows) + if (row.Index != -1) { - if (row.Index != -1) - { - lineNumList.Add(row.Index); - } + lineNumList.Add(row.Index); } - lineNumList.Sort(); - patternArgs.StartLine = lineNumList[0]; - patternArgs.EndLine = lineNumList[^1]; + } + lineNumList.Sort(); + patternArgs.StartLine = lineNumList[0]; + patternArgs.EndLine = lineNumList[^1]; + } + else + { + if (dataGridView.CurrentCellAddress.Y != -1) + { + patternArgs.StartLine = dataGridView.CurrentCellAddress.Y; } else { - if (dataGridView.CurrentCellAddress.Y != -1) - { - patternArgs.StartLine = dataGridView.CurrentCellAddress.Y; - } - else - { - patternArgs.StartLine = 0; - } - patternArgs.EndLine = dataGridView.RowCount - 1; + patternArgs.StartLine = 0; } + patternArgs.EndLine = dataGridView.RowCount - 1; } + } + + public void PatternStatistic (PatternArgs patternArgs) + { + var fx = new PatternStatisticFx(TestStatistic); + fx.BeginInvoke(patternArgs, null, null); + } - public void PatternStatistic(PatternArgs patternArgs) + public void ExportBookmarkList () + { + SaveFileDialog dlg = new() { - PatternStatisticFx fx = new PatternStatisticFx(TestStatistic); - fx.BeginInvoke(patternArgs, null, null); - } + Title = "Choose a file to save bookmarks into", + AddExtension = true, + DefaultExt = "csv", + Filter = "CSV file (*.csv)|*.csv|Bookmark file (*.bmk)|*.bmk", + FilterIndex = 1, + FileName = Path.GetFileNameWithoutExtension(FileName) + }; - public void ExportBookmarkList() + if (dlg.ShowDialog() == DialogResult.OK) { - SaveFileDialog dlg = new() + try { - Title = "Choose a file to save bookmarks into", - AddExtension = true, - DefaultExt = "csv", - Filter = "CSV file (*.csv)|*.csv|Bookmark file (*.bmk)|*.bmk", - FilterIndex = 1, - FileName = Path.GetFileNameWithoutExtension(FileName) - }; - - if (dlg.ShowDialog() == DialogResult.OK) + BookmarkExporter.ExportBookmarkList(_bookmarkProvider.BookmarkList, FileName, + dlg.FileName); + } + catch (IOException e) { - try - { - BookmarkExporter.ExportBookmarkList(_bookmarkProvider.BookmarkList, FileName, - dlg.FileName); - } - catch (IOException e) - { - _logger.Error(e); - MessageBox.Show("Error while exporting bookmark list: " + e.Message, "LogExpert"); - } + _logger.Error(e); + MessageBox.Show("Error while exporting bookmark list: " + e.Message, "LogExpert"); } } + } - public void ImportBookmarkList() + public void ImportBookmarkList () + { + OpenFileDialog dlg = new() { - OpenFileDialog dlg = new() - { - Title = "Choose a file to load bookmarks from", - AddExtension = true, - DefaultExt = "csv", - Filter = "CSV file (*.csv)|*.csv|Bookmark file (*.bmk)|*.bmk", - FilterIndex = 1, - FileName = Path.GetFileNameWithoutExtension(FileName) - }; + Title = "Choose a file to load bookmarks from", + AddExtension = true, + DefaultExt = "csv", + Filter = "CSV file (*.csv)|*.csv|Bookmark file (*.bmk)|*.bmk", + FilterIndex = 1, + FileName = Path.GetFileNameWithoutExtension(FileName) + }; - if (dlg.ShowDialog() == DialogResult.OK) + if (dlg.ShowDialog() == DialogResult.OK) + { + try { - try - { - // add to the existing bookmarks - SortedList newBookmarks = []; - BookmarkExporter.ImportBookmarkList(FileName, dlg.FileName, newBookmarks); + // add to the existing bookmarks + SortedList newBookmarks = []; + BookmarkExporter.ImportBookmarkList(FileName, dlg.FileName, newBookmarks); - // Add (or replace) to existing bookmark list - bool bookmarkAdded = false; - foreach (Bookmark b in newBookmarks.Values) + // Add (or replace) to existing bookmark list + var bookmarkAdded = false; + foreach (Bookmark b in newBookmarks.Values) + { + if (!_bookmarkProvider.BookmarkList.ContainsKey(b.LineNum)) { - if (!_bookmarkProvider.BookmarkList.ContainsKey(b.LineNum)) - { - _bookmarkProvider.BookmarkList.Add(b.LineNum, b); - bookmarkAdded = true; // refresh the list only once at the end - } - else - { - Bookmark existingBookmark = _bookmarkProvider.BookmarkList[b.LineNum]; - existingBookmark.Text = - b.Text; // replace existing bookmark for that line, preserving the overlay - OnBookmarkTextChanged(b); - } + _bookmarkProvider.BookmarkList.Add(b.LineNum, b); + bookmarkAdded = true; // refresh the list only once at the end } - - // Refresh the lists - if (bookmarkAdded) + else { - OnBookmarkAdded(); + Bookmark existingBookmark = _bookmarkProvider.BookmarkList[b.LineNum]; + existingBookmark.Text = + b.Text; // replace existing bookmark for that line, preserving the overlay + OnBookmarkTextChanged(b); } - dataGridView.Refresh(); - filterGridView.Refresh(); } - catch (IOException e) + + // Refresh the lists + if (bookmarkAdded) { - _logger.Error(e); - MessageBox.Show($"Error while importing bookmark list: {e.Message}", "LogExpert"); + OnBookmarkAdded(); } + dataGridView.Refresh(); + filterGridView.Refresh(); + } + catch (IOException e) + { + _logger.Error(e); + MessageBox.Show($"Error while importing bookmark list: {e.Message}", "LogExpert"); } } + } - public bool IsAdvancedOptionActive() - { - return rangeCheckBox.Checked || - fuzzyKnobControl.Value > 0 || - filterKnobBackSpread.Value > 0 || - filterKnobForeSpread.Value > 0 || - invertFilterCheckBox.Checked || - columnRestrictCheckBox.Checked; - } + public bool IsAdvancedOptionActive () + { + return rangeCheckBox.Checked || + fuzzyKnobControl.Value > 0 || + filterKnobBackSpread.Value > 0 || + filterKnobForeSpread.Value > 0 || + invertFilterCheckBox.Checked || + columnRestrictCheckBox.Checked; + } + + public void HandleChangedFilterList () + { + Invoke(new MethodInvoker(HandleChangedFilterListWorker)); + } - public void HandleChangedFilterList() + public void HandleChangedFilterListWorker () + { + var index = filterListBox.SelectedIndex; + filterListBox.Items.Clear(); + foreach (FilterParams filterParam in ConfigManager.Settings.filterList) { - Invoke(new MethodInvoker(HandleChangedFilterListWorker)); + filterListBox.Items.Add(filterParam); } - - public void HandleChangedFilterListWorker() + filterListBox.Refresh(); + if (index >= 0 && index < filterListBox.Items.Count) { - int index = filterListBox.SelectedIndex; - filterListBox.Items.Clear(); - foreach (FilterParams filterParam in ConfigManager.Settings.filterList) - { - filterListBox.Items.Add(filterParam); - } - filterListBox.Refresh(); - if (index >= 0 && index < filterListBox.Items.Count) - { - filterListBox.SelectedIndex = index; - } - filterOnLoadCheckBox.Checked = Preferences.isFilterOnLoad; - hideFilterListOnLoadCheckBox.Checked = Preferences.isAutoHideFilterList; + filterListBox.SelectedIndex = index; } + filterOnLoadCheckBox.Checked = Preferences.isFilterOnLoad; + hideFilterListOnLoadCheckBox.Checked = Preferences.isAutoHideFilterList; + } - public void SetCurrentHighlightGroup(string groupName) + public void SetCurrentHighlightGroup (string groupName) + { + _guiStateArgs.HighlightGroupName = groupName; + lock (_currentHighlightGroupLock) { - _guiStateArgs.HighlightGroupName = groupName; - lock (_currentHighlightGroupLock) + _currentHighlightGroup = _parentLogTabWin.FindHighlightGroup(groupName); + if (_currentHighlightGroup == null) { - _currentHighlightGroup = _parentLogTabWin.FindHighlightGroup(groupName); - if (_currentHighlightGroup == null) + if (_parentLogTabWin.HighlightGroupList.Count > 0) { - if (_parentLogTabWin.HighlightGroupList.Count > 0) - { - _currentHighlightGroup = _parentLogTabWin.HighlightGroupList[0]; - } - else - { - _currentHighlightGroup = new HighlightGroup(); - } + _currentHighlightGroup = _parentLogTabWin.HighlightGroupList[0]; + } + else + { + _currentHighlightGroup = new HighlightGroup(); } - _guiStateArgs.HighlightGroupName = _currentHighlightGroup.GroupName; } - SendGuiStateUpdate(); - BeginInvoke(new MethodInvoker(RefreshAllGrids)); + _guiStateArgs.HighlightGroupName = _currentHighlightGroup.GroupName; } + SendGuiStateUpdate(); + BeginInvoke(new MethodInvoker(RefreshAllGrids)); + } - public void SwitchMultiFile(bool enabled) - { - IsMultiFile = enabled; - Reload(); - } + public void SwitchMultiFile (bool enabled) + { + IsMultiFile = enabled; + Reload(); + } - public void AddOtherWindowToTimesync(LogWindow other) + public void AddOtherWindowToTimesync (LogWindow other) + { + if (other.IsTimeSynced) { - if (other.IsTimeSynced) + if (IsTimeSynced) { - if (IsTimeSynced) - { - other.FreeFromTimeSync(); - AddSlaveToTimesync(other); - } - else - { - AddToTimeSync(other); - } + other.FreeFromTimeSync(); + AddSlaveToTimesync(other); } else { - AddSlaveToTimesync(other); + AddToTimeSync(other); } } - - public void AddToTimeSync(LogWindow master) + else { - _logger.Info("Syncing window for {0} to {1}", Util.GetNameFromPath(FileName), Util.GetNameFromPath(master.FileName)); - lock (_timeSyncListLock) - { - if (IsTimeSynced && master.TimeSyncList != TimeSyncList) - // already synced but master has different sync list - { - FreeFromTimeSync(); - } - TimeSyncList = master.TimeSyncList; - TimeSyncList.AddWindow(this); - ScrollToTimestamp(TimeSyncList.CurrentTimestamp, false, false); - } - OnSyncModeChanged(); + AddSlaveToTimesync(other); } + } - public void FreeFromTimeSync() + public void AddToTimeSync (LogWindow master) + { + _logger.Info("Syncing window for {0} to {1}", Util.GetNameFromPath(FileName), Util.GetNameFromPath(master.FileName)); + lock (_timeSyncListLock) { - lock (_timeSyncListLock) + if (IsTimeSynced && master.TimeSyncList != TimeSyncList) + // already synced but master has different sync list { - if (TimeSyncList != null) - { - _logger.Info("De-Syncing window for {0}", Util.GetNameFromPath(FileName)); - TimeSyncList.WindowRemoved -= OnTimeSyncListWindowRemoved; - TimeSyncList.RemoveWindow(this); - TimeSyncList = null; - } + FreeFromTimeSync(); } - OnSyncModeChanged(); + TimeSyncList = master.TimeSyncList; + TimeSyncList.AddWindow(this); + ScrollToTimestamp(TimeSyncList.CurrentTimestamp, false, false); } + OnSyncModeChanged(); + } - public void RefreshLogView() + public void FreeFromTimeSync () + { + lock (_timeSyncListLock) { - RefreshAllGrids(); + if (TimeSyncList != null) + { + _logger.Info("De-Syncing window for {0}", Util.GetNameFromPath(FileName)); + TimeSyncList.WindowRemoved -= OnTimeSyncListWindowRemoved; + TimeSyncList.RemoveWindow(this); + TimeSyncList = null; + } } + OnSyncModeChanged(); + } - #endregion + public void RefreshLogView () + { + RefreshAllGrids(); } + + #endregion } diff --git a/src/LogExpert.UI/Controls/LogWindow/PatternWindow.cs b/src/LogExpert.UI/Controls/LogWindow/PatternWindow.cs index b003c8bb..d7d9ae3b 100644 --- a/src/LogExpert.UI/Controls/LogWindow/PatternWindow.cs +++ b/src/LogExpert.UI/Controls/LogWindow/PatternWindow.cs @@ -6,355 +6,354 @@ using System.Drawing; using System.Windows.Forms; -namespace LogExpert.UI.Controls.LogWindow +namespace LogExpert.UI.Controls.LogWindow; + +internal partial class PatternWindow : Form //TODO: Can this be changed to UserControl? { - internal partial class PatternWindow : Form //TODO: Can this be changed to UserControl? + #region Fields + + private readonly List> blockList = []; + private PatternBlock currentBlock; + private List currentList; + + private readonly LogWindow logWindow; + private PatternArgs patternArgs = new(); + + #endregion + + #region cTor + + public PatternWindow() { - #region Fields + InitializeComponent(); + } - private readonly List> blockList = []; - private PatternBlock currentBlock; - private List currentList; + public PatternWindow(LogWindow logWindow) + { + this.logWindow = logWindow; + InitializeComponent(); + recalcButton.Enabled = false; + } - private readonly LogWindow logWindow; - private PatternArgs patternArgs = new(); + #endregion - #endregion + #region Properties - #region cTor + public int Fuzzy + { + set => fuzzyKnobControl.Value = value; + get => fuzzyKnobControl.Value; + } - public PatternWindow() - { - InitializeComponent(); - } + public int MaxDiff + { + set => maxDiffKnobControl.Value = value; + get => maxDiffKnobControl.Value; + } - public PatternWindow(LogWindow logWindow) - { - this.logWindow = logWindow; - InitializeComponent(); - recalcButton.Enabled = false; - } + public int MaxMisses + { + set => maxMissesKnobControl.Value = value; + get => maxMissesKnobControl.Value; + } - #endregion + public int Weight + { + set => weigthKnobControl.Value = value; + get => weigthKnobControl.Value; + } - #region Properties + #endregion - public int Fuzzy - { - set { fuzzyKnobControl.Value = value; } - get { return fuzzyKnobControl.Value; } - } + #region Public methods - public int MaxDiff + public void SetBlockList(List flatBlockList, PatternArgs patternArgs) + { + this.patternArgs = patternArgs; + blockList.Clear(); + List singeList = []; + //int blockId = -1; + for (var i = 0; i < flatBlockList.Count; ++i) { - set { maxDiffKnobControl.Value = value; } - get { return maxDiffKnobControl.Value; } + PatternBlock block = flatBlockList[i]; + singeList.Add(block); + //if (block.blockId != blockId) + //{ + // singeList = new List(); + // PatternBlock selfRefBlock = new PatternBlock(); + // selfRefBlock.targetStart = block.startLine; + // selfRefBlock.targetEnd = block.endLine; + // selfRefBlock.blockId = block.blockId; + // singeList.Add(selfRefBlock); + // singeList.Add(block); + // this.blockList.Add(singeList); + // blockId = block.blockId; + //} + //else + //{ + // singeList.Add(block); + //} } + blockList.Add(singeList); + Invoke(new MethodInvoker(SetBlockListGuiStuff)); + } - public int MaxMisses - { - set { maxMissesKnobControl.Value = value; } - get { return maxMissesKnobControl.Value; } - } - public int Weight - { - set { weigthKnobControl.Value = value; } - get { return weigthKnobControl.Value; } - } + public void SetColumnizer(ILogLineColumnizer columnizer) + { + logWindow.SetColumnizer(columnizer, patternHitsDataGridView); + logWindow.SetColumnizer(columnizer, contentDataGridView); + patternHitsDataGridView.Columns[0].Width = 20; + contentDataGridView.Columns[0].Width = 20; + + DataGridViewTextBoxColumn blockInfoColumn = new(); + blockInfoColumn.HeaderText = "Weight"; + blockInfoColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.NotSet; + blockInfoColumn.Resizable = DataGridViewTriState.False; + blockInfoColumn.DividerWidth = 1; + blockInfoColumn.ReadOnly = true; + blockInfoColumn.Width = 50; + + DataGridViewTextBoxColumn contentInfoColumn = new(); + contentInfoColumn.HeaderText = "Diff"; + contentInfoColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.NotSet; + contentInfoColumn.Resizable = DataGridViewTriState.False; + contentInfoColumn.DividerWidth = 1; + contentInfoColumn.ReadOnly = true; + contentInfoColumn.Width = 50; + + patternHitsDataGridView.Columns.Insert(1, blockInfoColumn); + contentDataGridView.Columns.Insert(1, contentInfoColumn); + } - #endregion + public void SetFont(string fontName, float fontSize) + { + Font font = new(new FontFamily(fontName), fontSize); + var lineSpacing = font.FontFamily.GetLineSpacing(FontStyle.Regular); + var lineSpacingPixel = font.Size * lineSpacing / font.FontFamily.GetEmHeight(FontStyle.Regular); + + patternHitsDataGridView.DefaultCellStyle.Font = font; + contentDataGridView.DefaultCellStyle.Font = font; + //this.lineHeight = font.Height + 4; + patternHitsDataGridView.RowTemplate.Height = font.Height + 4; + contentDataGridView.RowTemplate.Height = font.Height + 4; + } - #region Public methods + #endregion - public void SetBlockList(List flatBlockList, PatternArgs patternArgs) + #region Private Methods + + private void SetBlockListGuiStuff() + { + patternHitsDataGridView.RowCount = 0; + blockCountLabel.Text = "0"; + contentDataGridView.RowCount = 0; + blockLinesLabel.Text = "0"; + recalcButton.Enabled = true; + setRangeButton.Enabled = true; + if (blockList.Count > 0) { - this.patternArgs = patternArgs; - blockList.Clear(); - List singeList = []; - //int blockId = -1; - for (int i = 0; i < flatBlockList.Count; ++i) - { - PatternBlock block = flatBlockList[i]; - singeList.Add(block); - //if (block.blockId != blockId) - //{ - // singeList = new List(); - // PatternBlock selfRefBlock = new PatternBlock(); - // selfRefBlock.targetStart = block.startLine; - // selfRefBlock.targetEnd = block.endLine; - // selfRefBlock.blockId = block.blockId; - // singeList.Add(selfRefBlock); - // singeList.Add(block); - // this.blockList.Add(singeList); - // blockId = block.blockId; - //} - //else - //{ - // singeList.Add(block); - //} - } - blockList.Add(singeList); - Invoke(new MethodInvoker(SetBlockListGuiStuff)); + SetCurrentList(blockList[0]); } + } + private void SetCurrentList(List patternList) + { + patternHitsDataGridView.RowCount = 0; + currentList = patternList; + patternHitsDataGridView.RowCount = currentList.Count; + patternHitsDataGridView.Refresh(); + blockCountLabel.Text = "" + currentList.Count; + } - public void SetColumnizer(ILogLineColumnizer columnizer) - { - logWindow.SetColumnizer(columnizer, patternHitsDataGridView); - logWindow.SetColumnizer(columnizer, contentDataGridView); - patternHitsDataGridView.Columns[0].Width = 20; - contentDataGridView.Columns[0].Width = 20; - - DataGridViewTextBoxColumn blockInfoColumn = new(); - blockInfoColumn.HeaderText = "Weight"; - blockInfoColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.NotSet; - blockInfoColumn.Resizable = DataGridViewTriState.False; - blockInfoColumn.DividerWidth = 1; - blockInfoColumn.ReadOnly = true; - blockInfoColumn.Width = 50; - - DataGridViewTextBoxColumn contentInfoColumn = new(); - contentInfoColumn.HeaderText = "Diff"; - contentInfoColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.NotSet; - contentInfoColumn.Resizable = DataGridViewTriState.False; - contentInfoColumn.DividerWidth = 1; - contentInfoColumn.ReadOnly = true; - contentInfoColumn.Width = 50; - - patternHitsDataGridView.Columns.Insert(1, blockInfoColumn); - contentDataGridView.Columns.Insert(1, contentInfoColumn); - } + private int GetLineForHitGrid(int rowIndex) + { + int line; + line = currentList[rowIndex].targetStart; + return line; + } - public void SetFont(string fontName, float fontSize) - { - Font font = new(new FontFamily(fontName), fontSize); - int lineSpacing = font.FontFamily.GetLineSpacing(FontStyle.Regular); - float lineSpacingPixel = font.Size * lineSpacing / font.FontFamily.GetEmHeight(FontStyle.Regular); - - patternHitsDataGridView.DefaultCellStyle.Font = font; - contentDataGridView.DefaultCellStyle.Font = font; - //this.lineHeight = font.Height + 4; - patternHitsDataGridView.RowTemplate.Height = font.Height + 4; - contentDataGridView.RowTemplate.Height = font.Height + 4; - } + private int GetLineForContentGrid(int rowIndex) + { + int line; + line = currentBlock.targetStart + rowIndex; + return line; + } - #endregion + #endregion - #region Private Methods + #region Events handler - private void SetBlockListGuiStuff() + private void patternHitsDataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e) + { + if (currentList == null || e.RowIndex < 0) { - patternHitsDataGridView.RowCount = 0; - blockCountLabel.Text = "0"; - contentDataGridView.RowCount = 0; - blockLinesLabel.Text = "0"; - recalcButton.Enabled = true; - setRangeButton.Enabled = true; - if (blockList.Count > 0) - { - SetCurrentList(blockList[0]); - } + return; } - - private void SetCurrentList(List patternList) + var rowIndex = GetLineForHitGrid(e.RowIndex); + var colIndex = e.ColumnIndex; + if (colIndex == 1) { - patternHitsDataGridView.RowCount = 0; - currentList = patternList; - patternHitsDataGridView.RowCount = currentList.Count; - patternHitsDataGridView.Refresh(); - blockCountLabel.Text = "" + currentList.Count; + e.Value = currentList[e.RowIndex].weigth; } - - private int GetLineForHitGrid(int rowIndex) + else { - int line; - line = currentList[rowIndex].targetStart; - return line; + if (colIndex > 1) + { + colIndex--; // correct the additional inserted col + } + e.Value = logWindow.GetCellValue(rowIndex, colIndex); } + } - private int GetLineForContentGrid(int rowIndex) + private void patternHitsDataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) + { + if (currentList == null || e.RowIndex < 0) { - int line; - line = currentBlock.targetStart + rowIndex; - return line; + return; } - - #endregion - - #region Events handler - - private void patternHitsDataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e) + if (e.ColumnIndex == 1) { - if (currentList == null || e.RowIndex < 0) - { - return; - } - int rowIndex = GetLineForHitGrid(e.RowIndex); - int colIndex = e.ColumnIndex; - if (colIndex == 1) + e.PaintBackground(e.CellBounds, false); + var selCount = patternArgs.EndLine - patternArgs.StartLine; + var maxWeight = patternArgs.MaxDiffInBlock * selCount + selCount; + if (maxWeight > 0) { - e.Value = currentList[e.RowIndex].weigth; - } - else - { - if (colIndex > 1) - { - colIndex--; // correct the additional inserted col - } - e.Value = logWindow.GetCellValue(rowIndex, colIndex); + var width = (int)((int)e.Value / (double)maxWeight * e.CellBounds.Width); + Rectangle rect = new(e.CellBounds.X, e.CellBounds.Y, width, e.CellBounds.Height); + var alpha = 90 + (int)((int)e.Value / (double)maxWeight * 165); + var color = Color.FromArgb(alpha, 170, 180, 150); + Brush brush = new SolidBrush(color); + rect.Inflate(-2, -1); + e.Graphics.FillRectangle(brush, rect); + brush.Dispose(); } + e.PaintContent(e.CellBounds); + e.Handled = true; } - - private void patternHitsDataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) + else { - if (currentList == null || e.RowIndex < 0) - { - return; - } - if (e.ColumnIndex == 1) - { - e.PaintBackground(e.CellBounds, false); - int selCount = patternArgs.EndLine - patternArgs.StartLine; - int maxWeight = patternArgs.MaxDiffInBlock * selCount + selCount; - if (maxWeight > 0) - { - int width = (int)((int)e.Value / (double)maxWeight * e.CellBounds.Width); - Rectangle rect = new(e.CellBounds.X, e.CellBounds.Y, width, e.CellBounds.Height); - int alpha = 90 + (int)((int)e.Value / (double)maxWeight * 165); - Color color = Color.FromArgb(alpha, 170, 180, 150); - Brush brush = new SolidBrush(color); - rect.Inflate(-2, -1); - e.Graphics.FillRectangle(brush, rect); - brush.Dispose(); - } - e.PaintContent(e.CellBounds); - e.Handled = true; - } - else - { - BufferedDataGridView gridView = (BufferedDataGridView)sender; - int rowIndex = GetLineForHitGrid(e.RowIndex); - logWindow.CellPainting(gridView, rowIndex, e); - } + var gridView = (BufferedDataGridView)sender; + var rowIndex = GetLineForHitGrid(e.RowIndex); + logWindow.CellPainting(gridView, rowIndex, e); } + } - private void patternHitsDataGridView_MouseDoubleClick(object sender, MouseEventArgs e) - { - //if (this.currentList == null || patternHitsDataGridView.CurrentRow == null) - // return; - //int rowIndex = GetLineForHitGrid(patternHitsDataGridView.CurrentRow.Index); + private void patternHitsDataGridView_MouseDoubleClick(object sender, MouseEventArgs e) + { + //if (this.currentList == null || patternHitsDataGridView.CurrentRow == null) + // return; + //int rowIndex = GetLineForHitGrid(patternHitsDataGridView.CurrentRow.Index); - //this.logWindow.SelectLogLine(rowIndex); - } + //this.logWindow.SelectLogLine(rowIndex); + } - private void patternHitsDataGridView_CurrentCellChanged(object sender, EventArgs e) + private void patternHitsDataGridView_CurrentCellChanged(object sender, EventArgs e) + { + if (currentList == null || patternHitsDataGridView.CurrentRow == null) { - if (currentList == null || patternHitsDataGridView.CurrentRow == null) - { - return; - } - if (patternHitsDataGridView.CurrentRow.Index > currentList.Count - 1) - { - return; - } - contentDataGridView.RowCount = 0; - currentBlock = currentList[patternHitsDataGridView.CurrentRow.Index]; - contentDataGridView.RowCount = currentBlock.targetEnd - currentBlock.targetStart + 1; - contentDataGridView.Refresh(); - contentDataGridView.CurrentCell = contentDataGridView.Rows[0].Cells[0]; - blockLinesLabel.Text = "" + contentDataGridView.RowCount; + return; } + if (patternHitsDataGridView.CurrentRow.Index > currentList.Count - 1) + { + return; + } + contentDataGridView.RowCount = 0; + currentBlock = currentList[patternHitsDataGridView.CurrentRow.Index]; + contentDataGridView.RowCount = currentBlock.targetEnd - currentBlock.targetStart + 1; + contentDataGridView.Refresh(); + contentDataGridView.CurrentCell = contentDataGridView.Rows[0].Cells[0]; + blockLinesLabel.Text = "" + contentDataGridView.RowCount; + } - private void contentDataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e) + private void contentDataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e) + { + if (currentBlock == null || e.RowIndex < 0) { - if (currentBlock == null || e.RowIndex < 0) - { - return; - } - int rowIndex = GetLineForContentGrid(e.RowIndex); - int colIndex = e.ColumnIndex; - if (colIndex == 1) + return; + } + var rowIndex = GetLineForContentGrid(e.RowIndex); + var colIndex = e.ColumnIndex; + if (colIndex == 1) + { + QualityInfo qi; + if (currentBlock.qualityInfoList.TryGetValue(rowIndex, out qi)) { - QualityInfo qi; - if (currentBlock.qualityInfoList.TryGetValue(rowIndex, out qi)) - { - e.Value = qi.quality; - } - else - { - e.Value = ""; - } + e.Value = qi.quality; } else { - if (colIndex != 0) - { - colIndex--; // adjust the inserted column - } - e.Value = logWindow.GetCellValue(rowIndex, colIndex); + e.Value = ""; } } - - private void contentDataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) + else { - if (currentBlock == null || e.RowIndex < 0) + if (colIndex != 0) { - return; + colIndex--; // adjust the inserted column } - BufferedDataGridView gridView = (BufferedDataGridView)sender; - int rowIndex = GetLineForContentGrid(e.RowIndex); - logWindow.CellPainting(gridView, rowIndex, e); + e.Value = logWindow.GetCellValue(rowIndex, colIndex); } + } - private void contentDataGridView_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e) + private void contentDataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) + { + if (currentBlock == null || e.RowIndex < 0) { - if (currentBlock == null || contentDataGridView.CurrentRow == null) - { - return; - } - int rowIndex = GetLineForContentGrid(contentDataGridView.CurrentRow.Index); - - logWindow.SelectLogLine(rowIndex); + return; } + var gridView = (BufferedDataGridView)sender; + var rowIndex = GetLineForContentGrid(e.RowIndex); + logWindow.CellPainting(gridView, rowIndex, e); + } - private void recalcButton_Click(object sender, EventArgs e) + private void contentDataGridView_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e) + { + if (currentBlock == null || contentDataGridView.CurrentRow == null) { - patternArgs.Fuzzy = fuzzyKnobControl.Value; - patternArgs.MaxDiffInBlock = maxDiffKnobControl.Value; - patternArgs.MaxMisses = maxMissesKnobControl.Value; - patternArgs.MinWeight = weigthKnobControl.Value; - logWindow.PatternStatistic(patternArgs); - recalcButton.Enabled = false; - setRangeButton.Enabled = false; + return; } + var rowIndex = GetLineForContentGrid(contentDataGridView.CurrentRow.Index); - private void closeButton_Click(object sender, EventArgs e) - { - Close(); - } + logWindow.SelectLogLine(rowIndex); + } - private void contentDataGridView_ColumnDividerDoubleClick(object sender, - DataGridViewColumnDividerDoubleClickEventArgs e) - { - e.Handled = true; - contentDataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); - } + private void recalcButton_Click(object sender, EventArgs e) + { + patternArgs.Fuzzy = fuzzyKnobControl.Value; + patternArgs.MaxDiffInBlock = maxDiffKnobControl.Value; + patternArgs.MaxMisses = maxMissesKnobControl.Value; + patternArgs.MinWeight = weigthKnobControl.Value; + logWindow.PatternStatistic(patternArgs); + recalcButton.Enabled = false; + setRangeButton.Enabled = false; + } - private void patternHitsDataGridView_ColumnDividerDoubleClick(object sender, - DataGridViewColumnDividerDoubleClickEventArgs e) - { - e.Handled = true; - patternHitsDataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); - } + private void closeButton_Click(object sender, EventArgs e) + { + Close(); + } - private void setRangeButton_Click(object sender, EventArgs e) - { - logWindow.PatternStatisticSelectRange(patternArgs); - recalcButton.Enabled = true; - rangeLabel.Text = "Start: " + patternArgs.StartLine + "\r\nEnd: " + patternArgs.EndLine; - } + private void contentDataGridView_ColumnDividerDoubleClick(object sender, + DataGridViewColumnDividerDoubleClickEventArgs e) + { + e.Handled = true; + contentDataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); + } - #endregion + private void patternHitsDataGridView_ColumnDividerDoubleClick(object sender, + DataGridViewColumnDividerDoubleClickEventArgs e) + { + e.Handled = true; + patternHitsDataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); } + + private void setRangeButton_Click(object sender, EventArgs e) + { + logWindow.PatternStatisticSelectRange(patternArgs); + recalcButton.Enabled = true; + rangeLabel.Text = "Start: " + patternArgs.StartLine + "\r\nEnd: " + patternArgs.EndLine; + } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.UI/Controls/LogWindow/RangeFinder.cs b/src/LogExpert.UI/Controls/LogWindow/RangeFinder.cs index 2a822e02..8fe836d7 100644 --- a/src/LogExpert.UI/Controls/LogWindow/RangeFinder.cs +++ b/src/LogExpert.UI/Controls/LogWindow/RangeFinder.cs @@ -7,100 +7,99 @@ using Range = LogExpert.Core.Entities.Range; -namespace LogExpert.UI.Controls.LogWindow +namespace LogExpert.UI.Controls.LogWindow; + +/// +/// Delivers the range (from..to) that matches the current range filter settings starting from a given line. +/// +public class RangeFinder(FilterParams filterParams, ColumnizerCallback callback) { - /// - /// Delivers the range (from..to) that matches the current range filter settings starting from a given line. - /// - public class RangeFinder(FilterParams filterParams, ColumnizerCallback callback) - { - #region Fields + #region Fields - private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); - private readonly FilterParams _filterParams = filterParams.CloneWithCurrentColumnizer(); + private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); + private readonly FilterParams _filterParams = filterParams.CloneWithCurrentColumnizer(); - #endregion + #endregion - #region Public methods + #region Public methods + + public Range FindRange(int startLine) + { + _logger.Info($"Starting range search for {_filterParams.SearchText} ... {_filterParams.RangeSearchText}"); - public Range FindRange(int startLine) + if (_filterParams.RangeSearchText == null || _filterParams.RangeSearchText.Trim().Length == 0) { - _logger.Info($"Starting range search for {_filterParams.SearchText} ... {_filterParams.RangeSearchText}"); + _logger.Info("Range search text not set. Cancelling range search."); + return null; + } + if (_filterParams.SearchText == null || _filterParams.SearchText.Trim().Length == 0) + { + _logger.Info("Search text not set. Cancelling range search."); + return null; + } - if (_filterParams.RangeSearchText == null || _filterParams.RangeSearchText.Trim().Length == 0) - { - _logger.Info("Range search text not set. Cancelling range search."); - return null; - } - if (_filterParams.SearchText == null || _filterParams.SearchText.Trim().Length == 0) - { - _logger.Info("Search text not set. Cancelling range search."); - return null; - } + _filterParams.IsRangeSearch = false; + _filterParams.IsInRange = false; - _filterParams.IsRangeSearch = false; - _filterParams.IsInRange = false; + var lineCount = callback.GetLineCount(); + var lineNum = startLine; + var foundStartLine = false; - int lineCount = callback.GetLineCount(); - int lineNum = startLine; - bool foundStartLine = false; + Range range = new(); + FilterParams tmpParam = _filterParams.CloneWithCurrentColumnizer(); - Range range = new(); - FilterParams tmpParam = _filterParams.CloneWithCurrentColumnizer(); + tmpParam.SearchText = _filterParams.RangeSearchText; - tmpParam.SearchText = _filterParams.RangeSearchText; + // search backward for starting keyword + var line = callback.GetLogLine(lineNum); - // search backward for starting keyword - var line = callback.GetLogLine(lineNum); + while (lineNum >= 0) + { + callback.LineNum = lineNum; - while (lineNum >= 0) + if (Util.TestFilterCondition(_filterParams, line, callback)) { - callback.LineNum = lineNum; - - if (Util.TestFilterCondition(_filterParams, line, callback)) - { - foundStartLine = true; - break; - } - lineNum--; - line = callback.GetLogLine(lineNum); - - if (lineNum < 0 || Util.TestFilterCondition(tmpParam, line, callback)) // do not crash on Ctrl+R when there is not start line found - { - // lower range bound found --> we are not in between a valid range - break; - } + foundStartLine = true; + break; } + lineNum--; + line = callback.GetLogLine(lineNum); - if (!foundStartLine) + if (lineNum < 0 || Util.TestFilterCondition(tmpParam, line, callback)) // do not crash on Ctrl+R when there is not start line found { - _logger.Info("Range start not found"); - return null; + // lower range bound found --> we are not in between a valid range + break; } + } - range.StartLine = lineNum; - _filterParams.IsRangeSearch = true; - _filterParams.IsInRange = true; - lineNum++; + if (!foundStartLine) + { + _logger.Info("Range start not found"); + return null; + } + + range.StartLine = lineNum; + _filterParams.IsRangeSearch = true; + _filterParams.IsInRange = true; + lineNum++; - while (lineNum < lineCount) + while (lineNum < lineCount) + { + line = callback.GetLogLine(lineNum); + callback.LineNum = lineNum; + if (!Util.TestFilterCondition(_filterParams, line, callback)) { - line = callback.GetLogLine(lineNum); - callback.LineNum = lineNum; - if (!Util.TestFilterCondition(_filterParams, line, callback)) - { - break; - } - lineNum++; + break; } - lineNum--; - range.EndLine = lineNum; - - _logger.Info($"Range search finished. Found {range.EndLine - range.StartLine} lines"); - - return range; + lineNum++; } + lineNum--; + range.EndLine = lineNum; + + _logger.Info($"Range search finished. Found {range.EndLine - range.StartLine} lines"); - #endregion + return range; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.UI/Controls/LogWindow/TimeSpreadCalculator.cs b/src/LogExpert.UI/Controls/LogWindow/TimeSpreadCalculator.cs index 47521d25..58c71e58 100644 --- a/src/LogExpert.UI/Controls/LogWindow/TimeSpreadCalculator.cs +++ b/src/LogExpert.UI/Controls/LogWindow/TimeSpreadCalculator.cs @@ -9,446 +9,445 @@ using System.Threading; using System.Threading.Tasks; -namespace LogExpert.UI.Controls.LogWindow +namespace LogExpert.UI.Controls.LogWindow; + +internal class TimeSpreadCalculator { - internal class TimeSpreadCalculator - { - #region Fields + #region Fields - private const int INACTIVITY_TIME = 2000; + private const int INACTIVITY_TIME = 2000; - private const int MAX_CONTRAST = 1300; - private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); + private const int MAX_CONTRAST = 1300; + private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); - private readonly EventWaitHandle _calcEvent = new ManualResetEvent(false); - private readonly ColumnizerCallback _callback; + private readonly EventWaitHandle _calcEvent = new ManualResetEvent(false); + private readonly ColumnizerCallback _callback; - private readonly object _diffListLock = new(); - private readonly EventWaitHandle _lineCountEvent = new ManualResetEvent(false); + private readonly object _diffListLock = new(); + private readonly EventWaitHandle _lineCountEvent = new ManualResetEvent(false); - //TODO Refactor that it does not need LogWindow - private readonly ILogWindow _logWindow; + //TODO Refactor that it does not need LogWindow + private readonly ILogWindow _logWindow; - // for DoCalc_via_Time - private double _average; + // for DoCalc_via_Time + private double _average; - private int _contrast = 400; - private int _displayHeight = 0; - private bool _enabled; - private DateTime _endTimestamp; - private int _lineCount = 0; - private int _maxDiff; - private TimeSpan _maxSpan; - private bool _shouldStop; - private CancellationTokenSource cts = new(); + private int _contrast = 400; + private int _displayHeight; + private bool _enabled; + private DateTime _endTimestamp; + private int _lineCount; + private int _maxDiff; + private TimeSpan _maxSpan; + private bool _shouldStop; + private CancellationTokenSource cts = new(); - private DateTime _startTimestamp; + private DateTime _startTimestamp; - private bool _timeMode = true; + private bool _timeMode = true; - // for DoCalc - private int _timePerLine; + // for DoCalc + private int _timePerLine; - #endregion + #endregion - #region cTor + #region cTor - public TimeSpreadCalculator(ILogWindow logWindow) - { - _logWindow = logWindow; - _callback = new ColumnizerCallback(_logWindow); + public TimeSpreadCalculator(ILogWindow logWindow) + { + _logWindow = logWindow; + _callback = new ColumnizerCallback(_logWindow); - Task.Run(WorkerFx, cts.Token); - } + Task.Run(WorkerFx, cts.Token); + } - #endregion + #endregion - #region Delegates + #region Delegates - public delegate void CalcDoneEventHandler(object sender, EventArgs e); + public delegate void CalcDoneEventHandler(object sender, EventArgs e); - public delegate void StartCalcEventHandler(object sender, EventArgs e); + public delegate void StartCalcEventHandler(object sender, EventArgs e); - #endregion + #endregion - #region Events + #region Events - public event CalcDoneEventHandler CalcDone; - public event StartCalcEventHandler StartCalc; + public event CalcDoneEventHandler CalcDone; + public event StartCalcEventHandler StartCalc; - #endregion + #endregion - #region Properties + #region Properties - public bool Enabled + public bool Enabled + { + get => _enabled; + set { - get => _enabled; - set + _enabled = value; + if (_enabled) { - _enabled = value; - if (_enabled) - { - _calcEvent.Set(); - _lineCountEvent.Set(); - } + _calcEvent.Set(); + _lineCountEvent.Set(); } } + } - public bool TimeMode + public bool TimeMode + { + get => _timeMode; + set { - get => _timeMode; - set + _timeMode = value; + if (_enabled) { - _timeMode = value; - if (_enabled) - { - _calcEvent.Set(); - _lineCountEvent.Set(); - } + _calcEvent.Set(); + _lineCountEvent.Set(); } } + } - public int Contrast + public int Contrast + { + set { - set + _contrast = value; + if (_contrast < 0) { - _contrast = value; - if (_contrast < 0) - { - _contrast = 0; - } - else if (_contrast > MAX_CONTRAST) - { - _contrast = MAX_CONTRAST; - } - - if (TimeMode) - { - CalcValuesViaTime(_maxDiff, _average); - } - else - { - CalcValuesViaLines(_timePerLine, _maxSpan); - } - OnCalcDone(EventArgs.Empty); + _contrast = 0; + } + else if (_contrast > MAX_CONTRAST) + { + _contrast = MAX_CONTRAST; } - get => _contrast; + if (TimeMode) + { + CalcValuesViaTime(_maxDiff, _average); + } + else + { + CalcValuesViaLines(_timePerLine, _maxSpan); + } + OnCalcDone(EventArgs.Empty); } - public List DiffList { get; set; } = []; + get => _contrast; + } + + public List DiffList { get; set; } = []; + + #endregion - #endregion + #region Public methods - #region Public methods + public void Stop() + { + _shouldStop = true; + _lineCountEvent.Set(); + cts.Cancel(); + } - public void Stop() + public void SetLineCount(int count) + { + _lineCount = count; + if (Enabled) { - _shouldStop = true; + _calcEvent.Set(); _lineCountEvent.Set(); - cts.Cancel(); } + } - public void SetLineCount(int count) + public void SetDisplayHeight(int height) + { + _displayHeight = height; + if (Enabled) { - _lineCount = count; - if (Enabled) - { - _calcEvent.Set(); - _lineCountEvent.Set(); - } + _calcEvent.Set(); + _lineCountEvent.Set(); } + } - public void SetDisplayHeight(int height) - { - _displayHeight = height; - if (Enabled) - { - _calcEvent.Set(); - _lineCountEvent.Set(); - } - } + #endregion - #endregion + #region Private Methods - #region Private Methods + private void WorkerFx() + { + //Thread.CurrentThread.Name = "TimeSpreadCalculator Worker"; + //Thread.CurrentThread.Priority = ThreadPriority.BelowNormal; - private void WorkerFx() + while (!_shouldStop) { - //Thread.CurrentThread.Name = "TimeSpreadCalculator Worker"; - //Thread.CurrentThread.Priority = ThreadPriority.BelowNormal; + // wait for wakeup + _lineCountEvent.WaitOne(); while (!_shouldStop) { - // wait for wakeup - _lineCountEvent.WaitOne(); - - while (!_shouldStop) + // wait for unbusy moments + _logger.Debug("TimeSpreadCalculator: wait for unbusy moments"); + var signaled = _calcEvent.WaitOne(INACTIVITY_TIME, false); + if (signaled == false) { - // wait for unbusy moments - _logger.Debug("TimeSpreadCalculator: wait for unbusy moments"); - bool signaled = _calcEvent.WaitOne(INACTIVITY_TIME, false); - if (signaled == false) + _logger.Debug("TimeSpreadCalculator: unbusy. starting calc."); + if (TimeMode) { - _logger.Debug("TimeSpreadCalculator: unbusy. starting calc."); - if (TimeMode) - { - DoCalc_via_Time(); - } - else - { - DoCalc(); - } - break; + DoCalc_via_Time(); } - - _logger.Debug("TimeSpreadCalculator: signalled. no calc."); - _calcEvent.Reset(); + else + { + DoCalc(); + } + break; } - _lineCountEvent.Reset(); + + _logger.Debug("TimeSpreadCalculator: signalled. no calc."); + _calcEvent.Reset(); } + _lineCountEvent.Reset(); } + } - private void DoCalc() + private void DoCalc() + { + OnStartCalc(EventArgs.Empty); + _logger.Debug("TimeSpreadCalculator.DoCalc() begin"); + + if (_callback.GetLineCount() < 1) { - OnStartCalc(EventArgs.Empty); - _logger.Debug("TimeSpreadCalculator.DoCalc() begin"); + OnCalcDone(EventArgs.Empty); + _logger.Debug("TimeSpreadCalculator.DoCalc() end because of line count < 1"); + return; + } - if (_callback.GetLineCount() < 1) - { - OnCalcDone(EventArgs.Empty); - _logger.Debug("TimeSpreadCalculator.DoCalc() end because of line count < 1"); - return; - } + var lineNum = 0; + var lastLineNum = _callback.GetLineCount() - 1; + _startTimestamp = _logWindow.GetTimestampForLineForward(ref lineNum, false); + _endTimestamp = _logWindow.GetTimestampForLine(ref lastLineNum, false); - int lineNum = 0; - int lastLineNum = _callback.GetLineCount() - 1; - _startTimestamp = _logWindow.GetTimestampForLineForward(ref lineNum, false); - _endTimestamp = _logWindow.GetTimestampForLine(ref lastLineNum, false); + var timePerLineSum = 0; - int timePerLineSum = 0; + if (_startTimestamp != DateTime.MinValue && _endTimestamp != DateTime.MinValue) + { + TimeSpan overallSpan = _endTimestamp - _startTimestamp; + var overallSpanMillis = (int)(overallSpan.Ticks / TimeSpan.TicksPerMillisecond); + _timePerLine = (int)Math.Round(overallSpanMillis / (double)_lineCount); + DateTime oldTime = _logWindow.GetTimestampForLineForward(ref lineNum, false); + int step; - if (_startTimestamp != DateTime.MinValue && _endTimestamp != DateTime.MinValue) + if (_lineCount > _displayHeight) { - TimeSpan overallSpan = _endTimestamp - _startTimestamp; - int overallSpanMillis = (int)(overallSpan.Ticks / TimeSpan.TicksPerMillisecond); - _timePerLine = (int)Math.Round(overallSpanMillis / (double)_lineCount); - DateTime oldTime = _logWindow.GetTimestampForLineForward(ref lineNum, false); - int step; - - if (_lineCount > _displayHeight) - { - step = (int)Math.Round(_lineCount / (double)_displayHeight); - } - else - { - step = 1; - } - - _logger.Debug("TimeSpreadCalculator.DoCalc() collecting data for {0} lines with step size {1}", lastLineNum, step); - - List newDiffList = []; - List maxList = []; - lineNum++; + step = (int)Math.Round(_lineCount / (double)_displayHeight); + } + else + { + step = 1; + } - for (int i = lineNum; i < lastLineNum; i += step) - { - int currLineNum = i; - DateTime time = _logWindow.GetTimestampForLineForward(ref currLineNum, false); - if (time != DateTime.MinValue) - { - TimeSpan span = time - oldTime; - maxList.Add(span); - timePerLineSum += (int)(span.Ticks / TimeSpan.TicksPerMillisecond); - newDiffList.Add(new SpreadEntry(i, 0, time)); - oldTime = time; - _logger.Debug("TimeSpreadCalculator.DoCalc() time diff {0}", span); - } - } + _logger.Debug("TimeSpreadCalculator.DoCalc() collecting data for {0} lines with step size {1}", lastLineNum, step); - if (maxList.Count > 3) - { - maxList.Sort(); - _maxSpan = maxList[^3]; - } + List newDiffList = []; + List maxList = []; + lineNum++; - lock (_diffListLock) + for (var i = lineNum; i < lastLineNum; i += step) + { + var currLineNum = i; + DateTime time = _logWindow.GetTimestampForLineForward(ref currLineNum, false); + if (time != DateTime.MinValue) { - DiffList = newDiffList; - _timePerLine = (int)Math.Round(timePerLineSum / ((double)(lastLineNum + 1) / step)); - CalcValuesViaLines(_timePerLine, _maxSpan); - OnCalcDone(EventArgs.Empty); - _logger.Debug("TimeSpreadCalculator.DoCalc() end"); + TimeSpan span = time - oldTime; + maxList.Add(span); + timePerLineSum += (int)(span.Ticks / TimeSpan.TicksPerMillisecond); + newDiffList.Add(new SpreadEntry(i, 0, time)); + oldTime = time; + _logger.Debug("TimeSpreadCalculator.DoCalc() time diff {0}", span); } } - } - - //TODO Refactor this method - private void DoCalc_via_Time() - { - OnStartCalc(EventArgs.Empty); - _logger.Debug("TimeSpreadCalculator.DoCalc_via_Time() begin"); - if (_callback.GetLineCount() < 1) + if (maxList.Count > 3) { - OnCalcDone(EventArgs.Empty); - _logger.Debug("TimeSpreadCalculator.DoCalc() end because of line count < 1"); - return; + maxList.Sort(); + _maxSpan = maxList[^3]; } - int lineNum = 0; - int lastLineNum = _callback.GetLineCount() - 1; - _startTimestamp = _logWindow.GetTimestampForLineForward(ref lineNum, false); - _endTimestamp = _logWindow.GetTimestampForLine(ref lastLineNum, false); - - if (_startTimestamp != DateTime.MinValue && _endTimestamp != DateTime.MinValue) + lock (_diffListLock) { - TimeSpan overallSpan = _endTimestamp - _startTimestamp; - long overallSpanMillis = overallSpan.Ticks / TimeSpan.TicksPerMillisecond; - //int timePerLine = (int)Math.Round((double)overallSpanMillis / (double)this.lineCount); + DiffList = newDiffList; + _timePerLine = (int)Math.Round(timePerLineSum / ((double)(lastLineNum + 1) / step)); + CalcValuesViaLines(_timePerLine, _maxSpan); + OnCalcDone(EventArgs.Empty); + _logger.Debug("TimeSpreadCalculator.DoCalc() end"); + } + } + } - long step; + //TODO Refactor this method + private void DoCalc_via_Time() + { + OnStartCalc(EventArgs.Empty); + _logger.Debug("TimeSpreadCalculator.DoCalc_via_Time() begin"); - if (overallSpanMillis > _displayHeight) - { - step = (long)Math.Round(overallSpanMillis / (double)_displayHeight); - } - else - { - step = 1; - } + if (_callback.GetLineCount() < 1) + { + OnCalcDone(EventArgs.Empty); + _logger.Debug("TimeSpreadCalculator.DoCalc() end because of line count < 1"); + return; + } - _logger.Debug("TimeSpreadCalculator.DoCalc_via_Time() time range is {0} ms", overallSpanMillis); + var lineNum = 0; + var lastLineNum = _callback.GetLineCount() - 1; + _startTimestamp = _logWindow.GetTimestampForLineForward(ref lineNum, false); + _endTimestamp = _logWindow.GetTimestampForLine(ref lastLineNum, false); - lineNum = 0; - DateTime searchTimeStamp = _startTimestamp; - int oldLineNum = lineNum; - int loopCount = 0; - int lineDiffSum = 0; - int minDiff = int.MaxValue; - _maxDiff = 0; - List maxList = []; - List newDiffList = []; + if (_startTimestamp != DateTime.MinValue && _endTimestamp != DateTime.MinValue) + { + TimeSpan overallSpan = _endTimestamp - _startTimestamp; + var overallSpanMillis = overallSpan.Ticks / TimeSpan.TicksPerMillisecond; + //int timePerLine = (int)Math.Round((double)overallSpanMillis / (double)this.lineCount); - while (searchTimeStamp.CompareTo(_endTimestamp) <= 0) - { - lineNum = _logWindow.FindTimestampLine_Internal(lineNum, lineNum, lastLineNum, searchTimeStamp, false); - if (lineNum < 0) - { - lineNum = -lineNum; - } - int lineDiff = lineNum - oldLineNum; + long step; - _logger.Debug("TimeSpreadCalculator.DoCalc_via_Time() test time {0:HH:mm:ss.fff} line diff={1}", searchTimeStamp, lineDiff); + if (overallSpanMillis > _displayHeight) + { + step = (long)Math.Round(overallSpanMillis / (double)_displayHeight); + } + else + { + step = 1; + } - if (lineDiff >= 0) - { - lineDiffSum += lineDiff; - newDiffList.Add(new SpreadEntry(lineNum, lineDiff, searchTimeStamp)); - - if (lineDiff < minDiff) - { - minDiff = lineDiff; - } - - if (lineDiff > _maxDiff) - { - _maxDiff = lineDiff; - } - maxList.Add(lineDiff); - loopCount++; - } + _logger.Debug("TimeSpreadCalculator.DoCalc_via_Time() time range is {0} ms", overallSpanMillis); - searchTimeStamp = searchTimeStamp.AddMilliseconds(step); - oldLineNum = lineNum; - //lineNum++; - } + lineNum = 0; + DateTime searchTimeStamp = _startTimestamp; + var oldLineNum = lineNum; + var loopCount = 0; + var lineDiffSum = 0; + var minDiff = int.MaxValue; + _maxDiff = 0; + List maxList = []; + List newDiffList = []; - if (maxList.Count > 3) + while (searchTimeStamp.CompareTo(_endTimestamp) <= 0) + { + lineNum = _logWindow.FindTimestampLine_Internal(lineNum, lineNum, lastLineNum, searchTimeStamp, false); + if (lineNum < 0) { - maxList.Sort(); - _maxDiff = maxList[^3]; + lineNum = -lineNum; } + var lineDiff = lineNum - oldLineNum; - _average = lineDiffSum / (double)loopCount; - //double average = maxList[maxList.Count / 2]; - _logger.Debug("Average diff={0} minDiff={1} maxDiff={2}", _average, minDiff, _maxDiff); + _logger.Debug("TimeSpreadCalculator.DoCalc_via_Time() test time {0:HH:mm:ss.fff} line diff={1}", searchTimeStamp, lineDiff); - lock (_diffListLock) + if (lineDiff >= 0) { - if (newDiffList.Count > 0) + lineDiffSum += lineDiff; + newDiffList.Add(new SpreadEntry(lineNum, lineDiff, searchTimeStamp)); + + if (lineDiff < minDiff) { - newDiffList.RemoveAt(0); + minDiff = lineDiff; } - if (newDiffList.Count > 0) + if (lineDiff > _maxDiff) { - newDiffList.RemoveAt(0); + _maxDiff = lineDiff; } - - DiffList = newDiffList; - CalcValuesViaTime(_maxDiff, _average); - OnCalcDone(EventArgs.Empty); - _logger.Debug("TimeSpreadCalculator.DoCalc_via_Time() end"); + maxList.Add(lineDiff); + loopCount++; } - } - } - private DateTime CalcValuesViaLines(int timePerLine, TimeSpan maxSpan) - { - DateTime oldTime = DateTime.MinValue; + searchTimeStamp = searchTimeStamp.AddMilliseconds(step); + oldLineNum = lineNum; + //lineNum++; + } - if (DiffList.Count > 0) + if (maxList.Count > 3) { - oldTime = DiffList[0].Timestamp; + maxList.Sort(); + _maxDiff = maxList[^3]; + } - foreach (SpreadEntry entry in DiffList) - { - TimeSpan span = entry.Timestamp - oldTime; - double diffFromAverage = (int)(span.Ticks / TimeSpan.TicksPerMillisecond) - timePerLine; + _average = lineDiffSum / (double)loopCount; + //double average = maxList[maxList.Count / 2]; + _logger.Debug("Average diff={0} minDiff={1} maxDiff={2}", _average, minDiff, _maxDiff); - if (diffFromAverage < 0) - { - diffFromAverage = 0; - } + lock (_diffListLock) + { + if (newDiffList.Count > 0) + { + newDiffList.RemoveAt(0); + } - int value = (int)(diffFromAverage / (timePerLine / TimeSpan.TicksPerMillisecond) * _contrast); - entry.Value = 255 - value; - oldTime = entry.Timestamp; + if (newDiffList.Count > 0) + { + newDiffList.RemoveAt(0); } - } - return oldTime; + DiffList = newDiffList; + CalcValuesViaTime(_maxDiff, _average); + OnCalcDone(EventArgs.Empty); + _logger.Debug("TimeSpreadCalculator.DoCalc_via_Time() end"); + } } + } - private void CalcValuesViaTime(int maxDiff, double average) + private DateTime CalcValuesViaLines(int timePerLine, TimeSpan maxSpan) + { + DateTime oldTime = DateTime.MinValue; + + if (DiffList.Count > 0) { + oldTime = DiffList[0].Timestamp; + foreach (SpreadEntry entry in DiffList) { - int lineDiff = entry.Diff; - double diffFromAverage = entry.Diff - average; + TimeSpan span = entry.Timestamp - oldTime; + double diffFromAverage = (int)(span.Ticks / TimeSpan.TicksPerMillisecond) - timePerLine; if (diffFromAverage < 0) { diffFromAverage = 0; } - int value = (int)(diffFromAverage / maxDiff * _contrast); - entry.Value = 255 - value; - _logger.Debug("TimeSpreadCalculator.DoCalc() test time {0:HH:mm:ss.fff} line diff={1} value={2}", entry.Timestamp, lineDiff, value); + var value = (int)(diffFromAverage / (timePerLine / TimeSpan.TicksPerMillisecond) * _contrast); + entry.Value = 255 - value; + oldTime = entry.Timestamp; } } - private void OnCalcDone(EventArgs e) - { - CalcDone?.Invoke(this, e); - } + return oldTime; + } - private void OnStartCalc(EventArgs e) + private void CalcValuesViaTime(int maxDiff, double average) + { + foreach (SpreadEntry entry in DiffList) { - StartCalc?.Invoke(this, e); + var lineDiff = entry.Diff; + var diffFromAverage = entry.Diff - average; + + if (diffFromAverage < 0) + { + diffFromAverage = 0; + } + var value = (int)(diffFromAverage / maxDiff * _contrast); + entry.Value = 255 - value; + + _logger.Debug("TimeSpreadCalculator.DoCalc() test time {0:HH:mm:ss.fff} line diff={1} value={2}", entry.Timestamp, lineDiff, value); } + } - #endregion + private void OnCalcDone(EventArgs e) + { + CalcDone?.Invoke(this, e); } + + private void OnStartCalc(EventArgs e) + { + StartCalc?.Invoke(this, e); + } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.UI/Controls/LogWindow/TimeSpreadigControl.cs b/src/LogExpert.UI/Controls/LogWindow/TimeSpreadigControl.cs index 24f5dca7..952136e7 100644 --- a/src/LogExpert.UI/Controls/LogWindow/TimeSpreadigControl.cs +++ b/src/LogExpert.UI/Controls/LogWindow/TimeSpreadigControl.cs @@ -3,304 +3,303 @@ using LogExpert.UI.Extensions; using NLog; -namespace LogExpert.UI.Controls.LogWindow +namespace LogExpert.UI.Controls.LogWindow; + +internal partial class TimeSpreadingControl : UserControl { - internal partial class TimeSpreadingControl : UserControl - { - private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); + private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); - #region Fields + #region Fields - private Bitmap _bitmap = new(1, 1); - private int _displayHeight = 1; - private readonly int _edgeOffset = (int)Win32.GetSystemMetricsForDpi(Win32.SM_CYVSCROLL); - private int _lastMouseY = 0; - private readonly object _monitor = new(); - private int _rectHeight = 1; + private Bitmap _bitmap = new(1, 1); + private int _displayHeight = 1; + private readonly int _edgeOffset = (int)Win32.GetSystemMetricsForDpi(Win32.SM_CYVSCROLL); + private int _lastMouseY; + private readonly object _monitor = new(); + private int _rectHeight = 1; - private TimeSpreadCalculator _timeSpreadCalc; - private readonly ToolTip _toolTip; + private TimeSpreadCalculator _timeSpreadCalc; + private readonly ToolTip _toolTip; - #endregion + #endregion - #region cTor + #region cTor - public TimeSpreadingControl() - { - InitializeComponent(); - _toolTip = new ToolTip(); - Font = new Font("Courier New", 8.25F, FontStyle.Regular, GraphicsUnit.Point, 0); - _toolTip.InitialDelay = 0; - _toolTip.ReshowDelay = 0; - _toolTip.ShowAlways = true; - DoubleBuffered = false; - } + public TimeSpreadingControl() + { + InitializeComponent(); + _toolTip = new ToolTip(); + Font = new Font("Courier New", 8.25F, FontStyle.Regular, GraphicsUnit.Point, 0); + _toolTip.InitialDelay = 0; + _toolTip.ReshowDelay = 0; + _toolTip.ShowAlways = true; + DoubleBuffered = false; + } - #endregion + #endregion - #region Delegates + #region Delegates - public delegate void LineSelectedEventHandler(object sender, SelectLineEventArgs e); + public delegate void LineSelectedEventHandler(object sender, SelectLineEventArgs e); - #endregion + #endregion - #region Events + #region Events - public event LineSelectedEventHandler LineSelected; + public event LineSelectedEventHandler LineSelected; - #endregion + #endregion - #region Properties + #region Properties - public bool ReverseAlpha { get; set; } + public bool ReverseAlpha { get; set; } - internal TimeSpreadCalculator TimeSpreadCalc + internal TimeSpreadCalculator TimeSpreadCalc + { + get => _timeSpreadCalc; + set { - get => _timeSpreadCalc; - set - { - //timeSpreadCalc.CalcDone -= timeSpreadCalc_CalcDone; - _timeSpreadCalc = value; - _timeSpreadCalc.CalcDone += TimeSpreadCalc_CalcDone; - _timeSpreadCalc.StartCalc += TimeSpreadCalc_StartCalc; - } + //timeSpreadCalc.CalcDone -= timeSpreadCalc_CalcDone; + _timeSpreadCalc = value; + _timeSpreadCalc.CalcDone += TimeSpreadCalc_CalcDone; + _timeSpreadCalc.StartCalc += TimeSpreadCalc_StartCalc; } + } - #endregion + #endregion - #region Overrides + #region Overrides - protected override void OnPaint(PaintEventArgs e) + protected override void OnPaint(PaintEventArgs e) + { + base.OnPaint(e); + lock (_monitor) { - base.OnPaint(e); - lock (_monitor) + if (DesignMode) { - if (DesignMode) - { - Brush bgBrush = new SolidBrush(Color.FromKnownColor(KnownColor.LightSkyBlue)); - Rectangle rect = ClientRectangle; - rect.Inflate(0, -_edgeOffset); - e.Graphics.FillRectangle(bgBrush, rect); - bgBrush.Dispose(); - } - else - { - e.Graphics.DrawImage(_bitmap, 0, _edgeOffset); - } + Brush bgBrush = new SolidBrush(Color.FromKnownColor(KnownColor.LightSkyBlue)); + Rectangle rect = ClientRectangle; + rect.Inflate(0, -_edgeOffset); + e.Graphics.FillRectangle(bgBrush, rect); + bgBrush.Dispose(); + } + else + { + e.Graphics.DrawImage(_bitmap, 0, _edgeOffset); } } + } - #endregion + #endregion - #region Private Methods + #region Private Methods - private SpreadEntry GetEntryForMouse(MouseEventArgs e) + private SpreadEntry GetEntryForMouse(MouseEventArgs e) + { + List list = TimeSpreadCalc.DiffList; + var y = e.Y - _edgeOffset; + if (y < 0) { - List list = TimeSpreadCalc.DiffList; - int y = e.Y - _edgeOffset; - if (y < 0) - { - y = 0; - } - else if (y >= ClientRectangle.Height - _edgeOffset * 3) - { - y = list.Count - 1; - } - else - { - y /= _rectHeight; - } - - lock (_monitor) - { - if (y >= list.Count || y < 0) - { - return null; - } - return list[y]; - } + y = 0; + } + else if (y >= ClientRectangle.Height - _edgeOffset * 3) + { + y = list.Count - 1; + } + else + { + y /= _rectHeight; } - private void DragContrast(MouseEventArgs e) + lock (_monitor) { - if (_lastMouseY == 0) + if (y >= list.Count || y < 0) { - _lastMouseY = _lastMouseY = e.Y; - return; + return null; } - _timeSpreadCalc.Contrast += (_lastMouseY - e.Y) * 5; - _lastMouseY = e.Y; + return list[y]; } + } - private void OnLineSelected(SelectLineEventArgs e) + private void DragContrast(MouseEventArgs e) + { + if (_lastMouseY == 0) { - LineSelected?.Invoke(this, e); + _lastMouseY = _lastMouseY = e.Y; + return; } + _timeSpreadCalc.Contrast += (_lastMouseY - e.Y) * 5; + _lastMouseY = e.Y; + } + + private void OnLineSelected(SelectLineEventArgs e) + { + LineSelected?.Invoke(this, e); + } - #endregion + #endregion - #region Events handler + #region Events handler - private void TimeSpreadCalc_CalcDone(object sender, EventArgs e) + private void TimeSpreadCalc_CalcDone(object sender, EventArgs e) + { + _logger.Debug("timeSpreadCalc_CalcDone()"); + + lock (_monitor) { - _logger.Debug("timeSpreadCalc_CalcDone()"); + Invalidate(); + Rectangle rect = ClientRectangle; + rect.Size = new Size(rect.Width, rect.Height - _edgeOffset * 3); - lock (_monitor) + if (rect.Height < 1) { - Invalidate(); - Rectangle rect = ClientRectangle; - rect.Size = new Size(rect.Width, rect.Height - _edgeOffset * 3); + return; + } - if (rect.Height < 1) - { - return; - } + _bitmap = new Bitmap(rect.Width, rect.Height); + var gfx = Graphics.FromImage(_bitmap); + Brush bgBrush = new SolidBrush(BackColor); + gfx.FillRectangle(bgBrush, rect); + bgBrush.Dispose(); - _bitmap = new Bitmap(rect.Width, rect.Height); - Graphics gfx = Graphics.FromImage(_bitmap); - Brush bgBrush = new SolidBrush(BackColor); - gfx.FillRectangle(bgBrush, rect); - bgBrush.Dispose(); + List list = TimeSpreadCalc.DiffList; + int step; - List list = TimeSpreadCalc.DiffList; - int step; + if (list.Count >= _displayHeight) + { + step = (int)Math.Round(list.Count / (double)_displayHeight); + _rectHeight = 1; + } + else + { + step = 1; + _rectHeight = (int)Math.Round(_displayHeight / (double)list.Count); + } - if (list.Count >= _displayHeight) - { - step = (int)Math.Round(list.Count / (double)_displayHeight); - _rectHeight = 1; - } - else + Rectangle fillRect = new(0, 0, rect.Width, _rectHeight); + + lock (list) + { + for (var i = 0; i < list.Count; i += step) { - step = 1; - _rectHeight = (int)Math.Round(_displayHeight / (double)list.Count); - } + SpreadEntry entry = list[i]; + var color = ReverseAlpha ? entry.Value : 255 - entry.Value; - Rectangle fillRect = new(0, 0, rect.Width, _rectHeight); + if (color > 255) + { + color = 255; + } - lock (list) - { - for (int i = 0; i < list.Count; i += step) + if (color < 0) { - SpreadEntry entry = list[i]; - int color = ReverseAlpha ? entry.Value : 255 - entry.Value; - - if (color > 255) - { - color = 255; - } - - if (color < 0) - { - color = 0; - } - - Brush brush = new SolidBrush(Color.FromArgb(color, ForeColor)); - //Brush brush = new SolidBrush(Color.FromArgb(color, color, color, color)); - gfx.FillRectangle(brush, fillRect); - brush.Dispose(); - fillRect.Offset(0, _rectHeight); + color = 0; } + + Brush brush = new SolidBrush(Color.FromArgb(color, ForeColor)); + //Brush brush = new SolidBrush(Color.FromArgb(color, color, color, color)); + gfx.FillRectangle(brush, fillRect); + brush.Dispose(); + fillRect.Offset(0, _rectHeight); } } - BeginInvoke(new MethodInvoker(Refresh)); } + BeginInvoke(new MethodInvoker(Refresh)); + } - private void TimeSpreadCalc_StartCalc(object sender, EventArgs e) + private void TimeSpreadCalc_StartCalc(object sender, EventArgs e) + { + lock (_monitor) { - lock (_monitor) - { - Invalidate(); - Rectangle rect = ClientRectangle; - rect.Size = new Size(rect.Width, rect.Height - _edgeOffset * 3); + Invalidate(); + Rectangle rect = ClientRectangle; + rect.Size = new Size(rect.Width, rect.Height - _edgeOffset * 3); - if (rect.Height < 1) - { - return; - } - - //this.bmp = new Bitmap(rect.Width, rect.Height); - Graphics gfx = Graphics.FromImage(_bitmap); + if (rect.Height < 1) + { + return; + } - Brush bgBrush = new SolidBrush(BackColor); - Brush fgBrush = new SolidBrush(ForeColor); - //gfx.FillRectangle(bgBrush, rect); + //this.bmp = new Bitmap(rect.Width, rect.Height); + var gfx = Graphics.FromImage(_bitmap); - StringFormat format = new(StringFormatFlags.DirectionVertical | StringFormatFlags.NoWrap); - format.LineAlignment = StringAlignment.Center; - format.Alignment = StringAlignment.Center; + Brush bgBrush = new SolidBrush(BackColor); + Brush fgBrush = new SolidBrush(ForeColor); + //gfx.FillRectangle(bgBrush, rect); - RectangleF rectf = new(rect.Left, rect.Top, rect.Width, rect.Height); + StringFormat format = new(StringFormatFlags.DirectionVertical | StringFormatFlags.NoWrap); + format.LineAlignment = StringAlignment.Center; + format.Alignment = StringAlignment.Center; - gfx.DrawString("Calculating time spread view...", Font, fgBrush, rectf, format); + RectangleF rectf = new(rect.Left, rect.Top, rect.Width, rect.Height); - bgBrush.Dispose(); - fgBrush.Dispose(); - } + gfx.DrawString("Calculating time spread view...", Font, fgBrush, rectf, format); - BeginInvoke(new MethodInvoker(Refresh)); + bgBrush.Dispose(); + fgBrush.Dispose(); } - private void TimeSpreadingControl_SizeChanged(object sender, EventArgs e) - { - if (TimeSpreadCalc != null) - { - _displayHeight = ClientRectangle.Height - _edgeOffset * 3; - TimeSpreadCalc.SetDisplayHeight(_displayHeight); - } - } + BeginInvoke(new MethodInvoker(Refresh)); + } - private void TimeSpreadingControl_MouseDown(object sender, MouseEventArgs e) + private void TimeSpreadingControl_SizeChanged(object sender, EventArgs e) + { + if (TimeSpreadCalc != null) { + _displayHeight = ClientRectangle.Height - _edgeOffset * 3; + TimeSpreadCalc.SetDisplayHeight(_displayHeight); } + } - private void TimeSpreadingControl_MouseUp(object sender, MouseEventArgs e) + private void TimeSpreadingControl_MouseDown(object sender, MouseEventArgs e) + { + } + + private void TimeSpreadingControl_MouseUp(object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Left) { - if (e.Button == MouseButtons.Left) + SpreadEntry entry = GetEntryForMouse(e); + if (entry == null) { - SpreadEntry entry = GetEntryForMouse(e); - if (entry == null) - { - return; - } - OnLineSelected(new SelectLineEventArgs(entry.LineNum)); + return; } + OnLineSelected(new SelectLineEventArgs(entry.LineNum)); } + } - private void TimeSpreadingControl_MouseEnter(object sender, EventArgs e) - { - _toolTip.Active = true; - } + private void TimeSpreadingControl_MouseEnter(object sender, EventArgs e) + { + _toolTip.Active = true; + } - private void TimeSpreadingControl_MouseLeave(object sender, EventArgs e) + private void TimeSpreadingControl_MouseLeave(object sender, EventArgs e) + { + _toolTip.Active = false; + } + + private void TimeSpreadingControl_MouseMove(object sender, MouseEventArgs e) + { + if (e.Y == _lastMouseY) { - _toolTip.Active = false; + return; } - private void TimeSpreadingControl_MouseMove(object sender, MouseEventArgs e) + if (e.Button == MouseButtons.Right) { - if (e.Y == _lastMouseY) - { - return; - } - - if (e.Button == MouseButtons.Right) - { - DragContrast(e); - return; - } + DragContrast(e); + return; + } - SpreadEntry entry = GetEntryForMouse(e); + SpreadEntry entry = GetEntryForMouse(e); - if (entry == null) - { - return; - } - _lastMouseY = e.Y; - string dts = entry.Timestamp.ToString("dd.MM.yyyy HH:mm:ss"); - _toolTip.SetToolTip(this, "Line " + (entry.LineNum + 1) + "\n" + dts); + if (entry == null) + { + return; } - - #endregion + _lastMouseY = e.Y; + var dts = entry.Timestamp.ToString("dd.MM.yyyy HH:mm:ss"); + _toolTip.SetToolTip(this, "Line " + (entry.LineNum + 1) + "\n" + dts); } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.UI/Controls/LogWindow/TimeSyncList.cs b/src/LogExpert.UI/Controls/LogWindow/TimeSyncList.cs index 5ed65d2c..bb5ac3c1 100644 --- a/src/LogExpert.UI/Controls/LogWindow/TimeSyncList.cs +++ b/src/LogExpert.UI/Controls/LogWindow/TimeSyncList.cs @@ -27,10 +27,7 @@ public class TimeSyncList public DateTime CurrentTimestamp { get; set; } - public int Count - { - get { return logWindowList.Count; } - } + public int Count => logWindowList.Count; #endregion @@ -54,6 +51,7 @@ public void RemoveWindow (LogWindow logWindow) { logWindowList.Remove(logWindow); } + OnWindowRemoved(); } @@ -90,10 +88,7 @@ public bool Contains (LogWindow logWindow) private void OnWindowRemoved () { - if (WindowRemoved != null) - { - WindowRemoved(this, new EventArgs()); - } + WindowRemoved?.Invoke(this, new EventArgs()); } #endregion diff --git a/src/LogExpert.UI/Dialogs/AboutBox.cs b/src/LogExpert.UI/Dialogs/AboutBox.cs index 129ff99b..632dd07c 100644 --- a/src/LogExpert.UI/Dialogs/AboutBox.cs +++ b/src/LogExpert.UI/Dialogs/AboutBox.cs @@ -31,7 +31,7 @@ public AboutBox() labelProductName.Text = AssemblyProduct; labelVersion.Text = AssemblyVersion; labelCopyright.Text = AssemblyCopyright; - string link = "https://github.com/LogExperts/LogExpert"; + var link = "https://github.com/LogExperts/LogExpert"; linkLabelURL.Links.Add(new LinkLabel.Link(0, link.Length, link)); LoadUsedComponents(); } @@ -40,7 +40,7 @@ public AboutBox() private void LoadUsedComponents() { - string json = File.ReadAllText($"{Application.StartupPath}files\\json\\usedComponents.json"); + var json = File.ReadAllText($"{Application.StartupPath}files\\json\\usedComponents.json"); var usedComponents = JsonConvert.DeserializeObject(json); usedComponents = usedComponents?.OrderBy(x => x.PackageId).ToArray(); usedComponentsDataGrid.DataSource = usedComponents; @@ -60,10 +60,10 @@ public string AssemblyTitle { get { - object[] attributes = _assembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false); + var attributes = _assembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false); if (attributes.Length > 0) { - AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0]; + var titleAttribute = (AssemblyTitleAttribute)attributes[0]; if (titleAttribute.Title != string.Empty) { return titleAttribute.Title; @@ -81,7 +81,7 @@ public string AssemblyVersion if (assembly.Version != null) { - string version = $"{assembly.Version.Major}.{assembly.Version.Minor}.{assembly.Version.Build}.{assembly.Version.Revision}"; + var version = $"{assembly.Version.Major}.{assembly.Version.Minor}.{assembly.Version.Build}.{assembly.Version.Revision}"; if (assembly.Version.Revision >= 9000) { version += " Testrelease"; @@ -99,7 +99,7 @@ public string AssemblyDescription { get { - object[] attributes = _assembly.GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false); + var attributes = _assembly.GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false); if (attributes.Length == 0) { @@ -113,7 +113,7 @@ public string AssemblyProduct { get { - object[] attributes = _assembly.GetCustomAttributes(typeof(AssemblyProductAttribute), false); + var attributes = _assembly.GetCustomAttributes(typeof(AssemblyProductAttribute), false); if (attributes.Length == 0) { return string.Empty; @@ -126,7 +126,7 @@ public string AssemblyCopyright { get { - object[] attributes = _assembly.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false); + var attributes = _assembly.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false); if (attributes.Length == 0) { return string.Empty; @@ -141,7 +141,7 @@ public string AssemblyCopyright private void OnLinkLabelURLClicked(object sender, LinkLabelLinkClickedEventArgs e) { - string? target = string.Empty; + var target = string.Empty; if (e.Link != null) { diff --git a/src/LogExpert.UI/Dialogs/BookmarkWindow.cs b/src/LogExpert.UI/Dialogs/BookmarkWindow.cs index eb79c2b7..6853a51e 100644 --- a/src/LogExpert.UI/Dialogs/BookmarkWindow.cs +++ b/src/LogExpert.UI/Dialogs/BookmarkWindow.cs @@ -138,7 +138,7 @@ public void SetColumnizer (ILogLineColumnizer columnizer) public void ResizeColumns () { // this.bookmarkDataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); - for (int i = 2; i < bookmarkDataGridView.ColumnCount; ++i) + for (var i = 2; i < bookmarkDataGridView.ColumnCount; ++i) { bookmarkDataGridView.AutoResizeColumn(i, DataGridViewAutoSizeColumnMode.DisplayedCells); } @@ -157,7 +157,7 @@ public void UpdateView () /// public void BookmarkTextChanged (Bookmark bookmark) { - int rowIndex = bookmarkDataGridView.CurrentCellAddress.Y; + var rowIndex = bookmarkDataGridView.CurrentCellAddress.Y; if (rowIndex == -1) { return; @@ -181,7 +181,7 @@ public void SelectBookmark (int lineNum) UpdateView(); } - int row = bookmarkData.GetBookmarkIndexForLine(lineNum); + var row = bookmarkData.GetBookmarkIndexForLine(lineNum); bookmarkDataGridView.CurrentCell = bookmarkDataGridView.Rows[row].Cells[0]; } } @@ -296,7 +296,7 @@ private void CommentPainting (BufferedDataGridView gridView, int rowIndex, DataG else { // _logger.logDebug("CellPaint No Focus"); - Color color = Color.FromArgb(255, 170, 170, 170); + var color = Color.FromArgb(255, 170, 170, 170); brush = new SolidBrush(color); } @@ -383,7 +383,7 @@ private void boomarkDataGridView_CellPainting (object sender, DataGridViewCellPa return; } - int lineNum = bookmarkData.Bookmarks[e.RowIndex].LineNum; + var lineNum = bookmarkData.Bookmarks[e.RowIndex].LineNum; // if (e.ColumnIndex == 1) // { @@ -415,14 +415,14 @@ private void OnBoomarkDataGridViewCellValueNeeded (object sender, DataGridViewCe } Bookmark bookmarkForLine = bookmarkData.Bookmarks[e.RowIndex]; - int lineNum = bookmarkForLine.LineNum; + var lineNum = bookmarkForLine.LineNum; if (e.ColumnIndex == 1) { e.Value = bookmarkForLine.Text?.Replace('\n', ' ').Replace('\r', ' '); } else { - int columnIndex = e.ColumnIndex > 1 ? e.ColumnIndex - 1 : e.ColumnIndex; + var columnIndex = e.ColumnIndex > 1 ? e.ColumnIndex - 1 : e.ColumnIndex; e.Value = logPaintContext.GetCellValue(lineNum, columnIndex); } } @@ -451,7 +451,7 @@ private void bookmarkGridView_KeyDown (object sender, KeyEventArgs e) if (bookmarkDataGridView.CurrentCellAddress.Y >= 0 && bookmarkDataGridView.CurrentCellAddress.Y < bookmarkData.Bookmarks.Count) { - int lineNum = bookmarkData.Bookmarks[bookmarkDataGridView.CurrentCellAddress.Y].LineNum; + var lineNum = bookmarkData.Bookmarks[bookmarkDataGridView.CurrentCellAddress.Y].LineNum; logView.SelectLogLine(lineNum); } @@ -495,7 +495,7 @@ private void bookmarkTextBox_TextChanged (object sender, EventArgs e) return; // ignore all changes done while the control is disabled } - int rowIndex = bookmarkDataGridView.CurrentCellAddress.Y; + var rowIndex = bookmarkDataGridView.CurrentCellAddress.Y; if (rowIndex == -1) { return; @@ -553,12 +553,12 @@ private void bookmarkDataGridView_CellDoubleClick (object sender, DataGridViewCe // Toggle bookmark when double-clicking on the first column if (e.ColumnIndex == 0 && e.RowIndex >= 0 && bookmarkDataGridView.CurrentRow != null) { - int index = bookmarkDataGridView.CurrentRow.Index; - int lineNum = bookmarkData.Bookmarks[bookmarkDataGridView.CurrentRow.Index].LineNum; + var index = bookmarkDataGridView.CurrentRow.Index; + var lineNum = bookmarkData.Bookmarks[bookmarkDataGridView.CurrentRow.Index].LineNum; bookmarkData.ToggleBookmark(lineNum); // we don't ask for confirmation if the bookmark has an associated comment... - int boomarkCount = bookmarkData.Bookmarks.Count; + var boomarkCount = bookmarkData.Bookmarks.Count; bookmarkDataGridView.RowCount = boomarkCount; if (index < boomarkCount) @@ -595,7 +595,7 @@ private void bookmarkDataGridView_CellDoubleClick (object sender, DataGridViewCe if (bookmarkDataGridView.CurrentRow != null && e.RowIndex >= 0) { - int lineNum = bookmarkData.Bookmarks[bookmarkDataGridView.CurrentRow.Index].LineNum; + var lineNum = bookmarkData.Bookmarks[bookmarkDataGridView.CurrentRow.Index].LineNum; logView.SelectAndEnsureVisible(lineNum, true); } } @@ -634,7 +634,7 @@ private void BookmarkWindow_ClientSizeChanged (object sender, EventArgs e) if (Width > Height) { splitContainer1.Orientation = Orientation.Vertical; - int distance = Width - 200; + var distance = Width - 200; splitContainer1.SplitterDistance = distance > splitContainer1.Panel1MinSize ? distance : splitContainer1.Panel1MinSize; @@ -642,7 +642,7 @@ private void BookmarkWindow_ClientSizeChanged (object sender, EventArgs e) else { splitContainer1.Orientation = Orientation.Horizontal; - int distance = Height - 200; + var distance = Height - 200; splitContainer1.SplitterDistance = distance > splitContainer1.Panel1MinSize ? distance : splitContainer1.Panel1MinSize; diff --git a/src/LogExpert.UI/Dialogs/ChooseIconDlg.cs b/src/LogExpert.UI/Dialogs/ChooseIconDlg.cs index b88fd6c4..ddce747d 100644 --- a/src/LogExpert.UI/Dialogs/ChooseIconDlg.cs +++ b/src/LogExpert.UI/Dialogs/ChooseIconDlg.cs @@ -52,7 +52,7 @@ private void FillIconList() imageList.ImageSize = icons[1, 0].Size; iconListView.LargeImageList = imageList; - for (int i = 0; i < icons.GetLength(1); ++i) + for (var i = 0; i < icons.GetLength(1); ++i) { imageList.Images.Add(icons[1, i]); ListViewItem item = new() diff --git a/src/LogExpert.UI/Dialogs/Eminus/Eminus.cs b/src/LogExpert.UI/Dialogs/Eminus/Eminus.cs index 9d01c556..16698f1b 100644 --- a/src/LogExpert.UI/Dialogs/Eminus/Eminus.cs +++ b/src/LogExpert.UI/Dialogs/Eminus/Eminus.cs @@ -10,295 +10,294 @@ //TODO: This whole Eminus folder is not in use. Can be deleted? What is it? //[assembly: SupportedOSPlatform("windows")] -namespace LogExpert +namespace LogExpert; + +internal class Eminus : IContextMenuEntry, ILogExpertPluginConfigurator { - internal class Eminus : IContextMenuEntry, ILogExpertPluginConfigurator - { - #region Fields + #region Fields - private const string CFG_FILE_NAME = "eminus.json"; - private const string DOT = "."; - private const string DOUBLE_DOT = ":"; - private const string DISABLED = "_"; + private const string CFG_FILE_NAME = "eminus.json"; + private const string DOT = "."; + private const string DOUBLE_DOT = ":"; + private const string DISABLED = "_"; - private EminusConfig _config = new(); - private EminusConfigDlg dlg; - private EminusConfig tmpConfig = new(); + private EminusConfig _config = new(); + private EminusConfigDlg dlg; + private EminusConfig tmpConfig = new(); - #endregion + #endregion - #region Properties + #region Properties - public static string Text => "eminus"; + public static string Text => "eminus"; - #endregion + #endregion - #region Private Methods + #region Private Methods - private XmlDocument BuildParam(ILogLine line) + private XmlDocument BuildParam(ILogLine line) + { + var fullLogLine = line.FullLine; + // no Java stacktrace but some special logging of our applications at work: + if (fullLogLine.Contains("Exception of type", StringComparison.CurrentCulture) || + fullLogLine.Contains("Nested:", StringComparison.CurrentCulture)) { - string fullLogLine = line.FullLine; - // no Java stacktrace but some special logging of our applications at work: - if (fullLogLine.Contains("Exception of type", StringComparison.CurrentCulture) || - fullLogLine.Contains("Nested:", StringComparison.CurrentCulture)) + var pos = fullLogLine.IndexOf("created in "); + + if (pos == -1) { - int pos = fullLogLine.IndexOf("created in "); + return null; + } - if (pos == -1) + pos += "created in ".Length; + var endPos = fullLogLine.IndexOf(DOT, pos); + + if (endPos == -1) + { + return null; + } + + var className = fullLogLine[pos..endPos]; + pos = fullLogLine.IndexOf(DOUBLE_DOT, pos); + + if (pos == -1) + { + return null; + } + + var lineNum = fullLogLine[(pos + 1)..]; + XmlDocument doc = BuildXmlDocument(className, lineNum); + return doc; + } + + if (fullLogLine.Contains("at ", StringComparison.CurrentCulture)) + { + var str = fullLogLine.Trim(); + string className = null; + string lineNum = null; + var pos = str.IndexOf("at ") + 3; + str = str[pos..]; // remove 'at ' + var idx = str.IndexOfAny(['(', '$', '<']); + + if (idx != -1) + { + if (str[idx] == '$') { - return null; + className = str[..idx]; + } + else + { + pos = str.LastIndexOf(DOT, idx); + if (pos == -1) + { + return null; + } + className = str[..pos]; } - pos += "created in ".Length; - int endPos = fullLogLine.IndexOf(DOT, pos); + idx = str.LastIndexOf(DOUBLE_DOT); - if (endPos == -1) + if (idx == -1) { return null; } - string className = fullLogLine[pos..endPos]; - pos = fullLogLine.IndexOf(DOUBLE_DOT, pos); + pos = str.IndexOf(')', idx); if (pos == -1) { return null; } - string lineNum = fullLogLine[(pos + 1)..]; - XmlDocument doc = BuildXmlDocument(className, lineNum); - return doc; + lineNum = str.Substring(idx + 1, pos - idx - 1); } + /* + * + + + + + + + */ + + XmlDocument doc = BuildXmlDocument(className, lineNum); + return doc; + } + return null; + } - if (fullLogLine.Contains("at ", StringComparison.CurrentCulture)) - { - string str = fullLogLine.Trim(); - string className = null; - string lineNum = null; - int pos = str.IndexOf("at ") + 3; - str = str[pos..]; // remove 'at ' - int idx = str.IndexOfAny(['(', '$', '<']); - - if (idx != -1) - { - if (str[idx] == '$') - { - className = str[..idx]; - } - else - { - pos = str.LastIndexOf(DOT, idx); - if (pos == -1) - { - return null; - } - className = str[..pos]; - } - - idx = str.LastIndexOf(DOUBLE_DOT); + private XmlDocument BuildXmlDocument(string className, string lineNum) + { + XmlDocument xmlDoc = new(); + xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", "yes"); + XmlElement rootElement = xmlDoc.CreateElement("eminus"); + xmlDoc.AppendChild(rootElement); + rootElement.SetAttribute("authKey", _config.password); + + XmlElement loadElement = xmlDoc.CreateElement("loadclass"); + loadElement.SetAttribute("mode", "dialog"); + rootElement.AppendChild(loadElement); + + XmlElement elemClassName = xmlDoc.CreateElement("classname"); + XmlElement elemLineNum = xmlDoc.CreateElement("linenumber"); + elemClassName.InnerText = className; + elemLineNum.InnerText = lineNum; + loadElement.AppendChild(elemClassName); + loadElement.AppendChild(elemLineNum); + return xmlDoc; + } - if (idx == -1) - { - return null; - } + #endregion - pos = str.IndexOf(')', idx); + #region IContextMenuEntry Member - if (pos == -1) - { - return null; - } + public string GetMenuText(IList logLines, ILogLineColumnizer columnizer, ILogExpertCallback callback) + { + //not used + return string.Empty; + } - lineNum = str.Substring(idx + 1, pos - idx - 1); - } - /* - * - - - - - - - */ - - XmlDocument doc = BuildXmlDocument(className, lineNum); - return doc; - } - return null; + public string GetMenuText(int logLinesCount, ILogLineColumnizer columnizer, ILogLine logline) + { + if (logLinesCount == 1 && BuildParam(logline) != null) + { + return "Load class in Eclipse"; } - - private XmlDocument BuildXmlDocument(string className, string lineNum) + else { - XmlDocument xmlDoc = new(); - xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", "yes"); - XmlElement rootElement = xmlDoc.CreateElement("eminus"); - xmlDoc.AppendChild(rootElement); - rootElement.SetAttribute("authKey", _config.password); - - XmlElement loadElement = xmlDoc.CreateElement("loadclass"); - loadElement.SetAttribute("mode", "dialog"); - rootElement.AppendChild(loadElement); - - XmlElement elemClassName = xmlDoc.CreateElement("classname"); - XmlElement elemLineNum = xmlDoc.CreateElement("linenumber"); - elemClassName.InnerText = className; - elemLineNum.InnerText = lineNum; - loadElement.AppendChild(elemClassName); - loadElement.AppendChild(elemLineNum); - return xmlDoc; + return $"{DISABLED}Load class in Eclipse"; } + } - #endregion - - #region IContextMenuEntry Member + public void MenuSelected(IList logLines, ILogLineColumnizer columnizer, ILogExpertCallback callback) + { + //Not used + } - public string GetMenuText(IList logLines, ILogLineColumnizer columnizer, ILogExpertCallback callback) + public void MenuSelected(int logLinesCount, ILogLineColumnizer columnizer, ILogLine logline) + { + if (logLinesCount != 1) { - //not used - return string.Empty; + return; } - public string GetMenuText(int logLinesCount, ILogLineColumnizer columnizer, ILogLine logline) - { - if (logLinesCount == 1 && BuildParam(logline) != null) - { - return "Load class in Eclipse"; - } - else - { - return $"{DISABLED}Load class in Eclipse"; - } - } + XmlDocument doc = BuildParam(logline); - public void MenuSelected(IList logLines, ILogLineColumnizer columnizer, ILogExpertCallback callback) + if (doc == null) { - //Not used + MessageBox.Show("Cannot parse Java stack trace line", "LogExpert"); } - - public void MenuSelected(int logLinesCount, ILogLineColumnizer columnizer, ILogLine logline) + else { - if (logLinesCount != 1) + try { - return; + TcpClient client = new(_config.host, _config.port); + NetworkStream stream = client.GetStream(); + StreamWriter writer = new(stream); + doc.Save(writer); + writer.Flush(); + stream.Flush(); + writer.Close(); + stream.Close(500); + client.Close(); } - - XmlDocument doc = BuildParam(logline); - - if (doc == null) - { - MessageBox.Show("Cannot parse Java stack trace line", "LogExpert"); - } - else + catch (Exception e) { - try - { - TcpClient client = new(_config.host, _config.port); - NetworkStream stream = client.GetStream(); - StreamWriter writer = new(stream); - doc.Save(writer); - writer.Flush(); - stream.Flush(); - writer.Close(); - stream.Close(500); - client.Close(); - } - catch (Exception e) - { - MessageBox.Show(e.Message, "LogExpert"); - } + MessageBox.Show(e.Message, "LogExpert"); } } + } - #endregion + #endregion - #region ILogExpertPluginConfigurator Member + #region ILogExpertPluginConfigurator Member - public void LoadConfig(string configDir) - { - string configPath = configDir + CFG_FILE_NAME; + public void LoadConfig(string configDir) + { + var configPath = configDir + CFG_FILE_NAME; - FileInfo fileInfo = new(configDir + Path.DirectorySeparatorChar + CFG_FILE_NAME); + FileInfo fileInfo = new(configDir + Path.DirectorySeparatorChar + CFG_FILE_NAME); - if (!File.Exists(configPath)) + if (!File.Exists(configPath)) + { + _config = new EminusConfig(); + } + else + { + try { - _config = new EminusConfig(); + _config = JsonConvert.DeserializeObject(File.ReadAllText($"{fileInfo.FullName}")); } - else + catch (SerializationException e) { - try - { - _config = JsonConvert.DeserializeObject(File.ReadAllText($"{fileInfo.FullName}")); - } - catch (SerializationException e) - { - MessageBox.Show(e.Message, "Deserialize"); - _config = new EminusConfig(); - } + MessageBox.Show(e.Message, "Deserialize"); + _config = new EminusConfig(); } } + } - public void SaveConfig(string configDir) - { - FileInfo fileInfo = new(configDir + Path.DirectorySeparatorChar + CFG_FILE_NAME); + public void SaveConfig(string configDir) + { + FileInfo fileInfo = new(configDir + Path.DirectorySeparatorChar + CFG_FILE_NAME); - dlg?.ApplyChanges(); + dlg?.ApplyChanges(); - _config = tmpConfig.Clone(); + _config = tmpConfig.Clone(); - using StreamWriter sw = new(fileInfo.Create()); - JsonSerializer serializer = new(); - serializer.Serialize(sw, _config); - } + using StreamWriter sw = new(fileInfo.Create()); + JsonSerializer serializer = new(); + serializer.Serialize(sw, _config); + } - public bool HasEmbeddedForm() - { - return true; - } + public bool HasEmbeddedForm() + { + return true; + } - public void ShowConfigForm(object panel) + public void ShowConfigForm(object panel) + { + dlg = new EminusConfigDlg(tmpConfig) { - dlg = new EminusConfigDlg(tmpConfig) - { - Parent = (Panel)panel - }; - dlg.Show(); - } + Parent = (Panel)panel + }; + dlg.Show(); + } - /// - /// Implemented only for demonstration purposes. This function is called when the config button - /// is pressed (HasEmbeddedForm() must return false for this). - /// - /// - public void ShowConfigDialog(object owner) + /// + /// Implemented only for demonstration purposes. This function is called when the config button + /// is pressed (HasEmbeddedForm() must return false for this). + /// + /// + public void ShowConfigDialog(object owner) + { + dlg = new EminusConfigDlg(tmpConfig) { - dlg = new EminusConfigDlg(tmpConfig) - { - TopLevel = true, - Owner = (Form)owner - }; + TopLevel = true, + Owner = (Form)owner + }; - dlg.ShowDialog(); - dlg.ApplyChanges(); - } + dlg.ShowDialog(); + dlg.ApplyChanges(); + } - public void HideConfigForm() - { - if (dlg != null) - { - dlg.ApplyChanges(); - dlg.Hide(); - dlg.Dispose(); - dlg = null; - } - } - - public void StartConfig() + public void HideConfigForm() + { + if (dlg != null) { - tmpConfig = _config.Clone(); + dlg.ApplyChanges(); + dlg.Hide(); + dlg.Dispose(); + dlg = null; } + } - #endregion + public void StartConfig() + { + tmpConfig = _config.Clone(); } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.UI/Dialogs/Eminus/EminusConfig.cs b/src/LogExpert.UI/Dialogs/Eminus/EminusConfig.cs index 28586414..444e9dd8 100644 --- a/src/LogExpert.UI/Dialogs/Eminus/EminusConfig.cs +++ b/src/LogExpert.UI/Dialogs/Eminus/EminusConfig.cs @@ -1,31 +1,30 @@ using System; -namespace LogExpert +namespace LogExpert; + +[Serializable] +internal class EminusConfig { - [Serializable] - internal class EminusConfig - { - #region Fields + #region Fields - public string host = "127.0.0.1"; - public string password = ""; - public int port = 12345; + public string host = "127.0.0.1"; + public string password = ""; + public int port = 12345; - #endregion + #endregion - #region Public methods + #region Public methods - public EminusConfig Clone() + public EminusConfig Clone() + { + EminusConfig config = new() { - EminusConfig config = new() - { - host = host, - port = port, - password = password - }; - return config; - } - - #endregion + host = host, + port = port, + password = password + }; + return config; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.UI/Dialogs/Eminus/EminusConfigDlg.cs b/src/LogExpert.UI/Dialogs/Eminus/EminusConfigDlg.cs index 7568e0b1..8b43c982 100644 --- a/src/LogExpert.UI/Dialogs/Eminus/EminusConfigDlg.cs +++ b/src/LogExpert.UI/Dialogs/Eminus/EminusConfigDlg.cs @@ -2,59 +2,58 @@ using System.Drawing; using System.Windows.Forms; -namespace LogExpert +namespace LogExpert; + +internal partial class EminusConfigDlg : Form { - internal partial class EminusConfigDlg : Form - { - #region Fields + #region Fields - #endregion + #endregion - #region cTor + #region cTor - public EminusConfigDlg(EminusConfig config) - { - SuspendLayout(); + public EminusConfigDlg(EminusConfig config) + { + SuspendLayout(); - AutoScaleDimensions = new SizeF(96F, 96F); - AutoScaleMode = AutoScaleMode.Dpi; + AutoScaleDimensions = new SizeF(96F, 96F); + AutoScaleMode = AutoScaleMode.Dpi; - InitializeComponent(); + InitializeComponent(); - TopLevel = false; - Config = config; + TopLevel = false; + Config = config; - hostTextBox.Text = config.host; - portTextBox.Text = string.Empty + config.port; - passwordTextBox.Text = config.password; + hostTextBox.Text = config.host; + portTextBox.Text = string.Empty + config.port; + passwordTextBox.Text = config.password; - ResumeLayout(); - } + ResumeLayout(); + } - #endregion + #endregion - #region Properties + #region Properties - public EminusConfig Config { get; set; } + public EminusConfig Config { get; set; } - #endregion + #endregion - #region Public methods + #region Public methods - public void ApplyChanges() + public void ApplyChanges() + { + Config.host = hostTextBox.Text; + try { - Config.host = hostTextBox.Text; - try - { - Config.port = short.Parse(portTextBox.Text); - } - catch (FormatException) - { - Config.port = 0; - } - Config.password = passwordTextBox.Text; + Config.port = short.Parse(portTextBox.Text); } - - #endregion + catch (FormatException) + { + Config.port = 0; + } + Config.password = passwordTextBox.Text; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.UI/Dialogs/FilterColumnChooser.cs b/src/LogExpert.UI/Dialogs/FilterColumnChooser.cs index eb99587b..4a62edb8 100644 --- a/src/LogExpert.UI/Dialogs/FilterColumnChooser.cs +++ b/src/LogExpert.UI/Dialogs/FilterColumnChooser.cs @@ -38,10 +38,10 @@ public FilterColumnChooser(FilterParams filterParams) private void Init() { - int count = _columnizer.GetColumnCount(); - string[] names = _columnizer.GetColumnNames(); + var count = _columnizer.GetColumnCount(); + var names = _columnizer.GetColumnNames(); - for (int i = 0; i < count; ++i) + for (var i = 0; i < count; ++i) { columnListBox.Items.Add(names[i], _filterParams.ColumnList.Contains(i)); } diff --git a/src/LogExpert.UI/Dialogs/LogTabWindow/FilterSelectorForm.cs b/src/LogExpert.UI/Dialogs/LogTabWindow/FilterSelectorForm.cs index f0261e74..a23c253a 100644 --- a/src/LogExpert.UI/Dialogs/LogTabWindow/FilterSelectorForm.cs +++ b/src/LogExpert.UI/Dialogs/LogTabWindow/FilterSelectorForm.cs @@ -74,7 +74,7 @@ private void OnFilterComboBoxSelectedIndexChanged(object sender, EventArgs e) { ILogLineColumnizer col = _columnizerList[filterComboBox.SelectedIndex]; SelectedColumnizer = col; - string description = col.GetDescription(); + var description = col.GetDescription(); description += "\r\nSupports timeshift: " + (SelectedColumnizer.IsTimeshiftImplemented() ? "Yes" : "No"); commentTextBox.Text = description; configButton.Enabled = SelectedColumnizer is IColumnizerConfigurator; @@ -86,7 +86,7 @@ private void OnConfigButtonClick(object sender, EventArgs e) { if (SelectedColumnizer is IColumnizerConfigurator configurator) { - string configDir = ConfigManager.ConfigDir; + var configDir = ConfigManager.ConfigDir; if (ConfigManager.Settings.Preferences.PortableMode) { diff --git a/src/LogExpert.UI/Dialogs/LogTabWindow/HighlightDialog.cs b/src/LogExpert.UI/Dialogs/LogTabWindow/HighlightDialog.cs index 6ccfcb29..1b7a06a0 100644 --- a/src/LogExpert.UI/Dialogs/LogTabWindow/HighlightDialog.cs +++ b/src/LogExpert.UI/Dialogs/LogTabWindow/HighlightDialog.cs @@ -101,7 +101,7 @@ private void OnBtnCopyGroupClick(object sender, EventArgs e) { if (comboBoxGroups.SelectedIndex >= 0 && comboBoxGroups.SelectedIndex < HighlightGroupList.Count) { - HighlightGroup newGroup = (HighlightGroup)HighlightGroupList[comboBoxGroups.SelectedIndex].Clone(); + var newGroup = (HighlightGroup)HighlightGroupList[comboBoxGroups.SelectedIndex].Clone(); newGroup.GroupName = "Copy of " + newGroup.GroupName; HighlightGroupList.Add(newGroup); @@ -132,7 +132,7 @@ private void OnBtnDelGroupClick(object sender, EventArgs e) if (comboBoxGroups.SelectedIndex >= 0 && comboBoxGroups.SelectedIndex < HighlightGroupList.Count) { - int index = comboBoxGroups.SelectedIndex; + var index = comboBoxGroups.SelectedIndex; HighlightGroupList.RemoveAt(comboBoxGroups.SelectedIndex); FillGroupComboBox(); if (index < HighlightGroupList.Count) @@ -166,7 +166,7 @@ private void OnBtnExportGroupClick(object sender, EventArgs e) private void OnBtnGroupDownClick(object sender, EventArgs e) { - int index = comboBoxGroups.SelectedIndex; + var index = comboBoxGroups.SelectedIndex; if (index > -1 && index < _highlightGroupList.Count - 1) { _highlightGroupList.Reverse(index, 2); @@ -178,7 +178,7 @@ private void OnBtnGroupDownClick(object sender, EventArgs e) private void OnBtnGroupUpClick(object sender, EventArgs e) { - int index = comboBoxGroups.SelectedIndex; + var index = comboBoxGroups.SelectedIndex; if (index > 0) { _highlightGroupList.Reverse(index - 1, 2); @@ -240,11 +240,11 @@ private void OnBtnImportGroupClick(object sender, EventArgs e) private void OnBtnMoveDownClick(object sender, EventArgs e) { - int index = listBoxHighlight.SelectedIndex; + var index = listBoxHighlight.SelectedIndex; if (index > -1 && index < listBoxHighlight.Items.Count - 1) { - object item = listBoxHighlight.SelectedItem; + var item = listBoxHighlight.SelectedItem; listBoxHighlight.Items.RemoveAt(index); listBoxHighlight.Items.Insert(index + 1, item); listBoxHighlight.SelectedIndex = index + 1; @@ -254,10 +254,10 @@ private void OnBtnMoveDownClick(object sender, EventArgs e) private void OnBtnMoveUpClick(object sender, EventArgs e) { - int index = listBoxHighlight.SelectedIndex; + var index = listBoxHighlight.SelectedIndex; if (index > 0) { - object item = listBoxHighlight.SelectedItem; + var item = listBoxHighlight.SelectedItem; listBoxHighlight.Items.RemoveAt(index); // will also clear the selection listBoxHighlight.Items.Insert(index - 1, item); listBoxHighlight.SelectedIndex = index - 1; // restore the selection @@ -269,9 +269,9 @@ private void OnBtnNewGroupClick(object sender, EventArgs e) { // Propose a unique name const string baseName = "New group"; - string name = baseName; - bool uniqueName = false; - int i = 1; + var name = baseName; + var uniqueName = false; + var i = 1; while (!uniqueName) { uniqueName = HighlightGroupList.FindIndex(delegate (HighlightGroup g) { return g.GroupName == name; }) < 0; @@ -370,12 +370,12 @@ private void OnDeleteButtonClick(object sender, EventArgs e) { if (listBoxHighlight.SelectedIndex >= 0) { - int removeIndex = listBoxHighlight.SelectedIndex; + var removeIndex = listBoxHighlight.SelectedIndex; _currentGroup.HighlightEntryList.RemoveAt(removeIndex); listBoxHighlight.Items.RemoveAt(removeIndex); // Select previous (or first if none before) - int nextSelectIndex = removeIndex; + var nextSelectIndex = removeIndex; if (nextSelectIndex >= listBoxHighlight.Items.Count) { nextSelectIndex--; // if last item was removed, go one up @@ -412,7 +412,7 @@ private void OnHighlightListBoxDrawItem(object sender, DrawItemEventArgs e) e.DrawBackground(); if (e.Index >= 0) { - HighlightEntry entry = (HighlightEntry)listBoxHighlight.Items[e.Index]; + var entry = (HighlightEntry)listBoxHighlight.Items[e.Index]; Rectangle rectangle = new(0, e.Bounds.Top, e.Bounds.Width, e.Bounds.Height); if ((e.State & DrawItemState.Selected) != DrawItemState.Selected) @@ -519,7 +519,7 @@ private void ChooseColor(ColorComboBox comboBox) private void Dirty() { - int index = listBoxHighlight.SelectedIndex; + var index = listBoxHighlight.SelectedIndex; if (index > -1) { btnApply.Enabled = true; @@ -574,7 +574,7 @@ private void InitData() FillGroupComboBox(); _currentGroup = null; - string groupToSelect = PreSelectedGroupName; + var groupToSelect = PreSelectedGroupName; if (string.IsNullOrEmpty(groupToSelect)) { groupToSelect = def; @@ -599,10 +599,10 @@ private void InitData() private void ReEvaluateGroupButtonStates() { // Refresh button states based on the selection in the combobox - bool atLeastOneSelected = comboBoxGroups.SelectedItem != null; - bool moreThanOne = comboBoxGroups.Items.Count > 1; - bool firstSelected = atLeastOneSelected && comboBoxGroups.SelectedIndex == 0; - bool lastSelected = atLeastOneSelected && comboBoxGroups.SelectedIndex == comboBoxGroups.Items.Count - 1; + var atLeastOneSelected = comboBoxGroups.SelectedItem != null; + var moreThanOne = comboBoxGroups.Items.Count > 1; + var firstSelected = atLeastOneSelected && comboBoxGroups.SelectedIndex == 0; + var lastSelected = atLeastOneSelected && comboBoxGroups.SelectedIndex == comboBoxGroups.Items.Count - 1; btnDeleteGroup.Enabled = atLeastOneSelected; btnCopyGroup.Enabled = atLeastOneSelected; @@ -613,10 +613,10 @@ private void ReEvaluateGroupButtonStates() private void ReEvaluateHighlightButtonStates() { // Refresh button states based on the selection in the combobox - bool atLeastOneSelected = listBoxHighlight.SelectedItem != null; - bool moreThanOne = listBoxHighlight.Items.Count > 1; - bool firstSelected = atLeastOneSelected && listBoxHighlight.SelectedIndex == 0; - bool lastSelected = atLeastOneSelected && listBoxHighlight.SelectedIndex == listBoxHighlight.Items.Count - 1; + var atLeastOneSelected = listBoxHighlight.SelectedItem != null; + var moreThanOne = listBoxHighlight.Items.Count > 1; + var firstSelected = atLeastOneSelected && listBoxHighlight.SelectedIndex == 0; + var lastSelected = atLeastOneSelected && listBoxHighlight.SelectedIndex == listBoxHighlight.Items.Count - 1; btnDelete.Enabled = atLeastOneSelected; btnMoveUp.Enabled = atLeastOneSelected && moreThanOne && !firstSelected; @@ -629,7 +629,7 @@ private void SaveEntry() { CheckRegex(); - HighlightEntry entry = (HighlightEntry)listBoxHighlight.SelectedItem; + var entry = (HighlightEntry)listBoxHighlight.SelectedItem; entry.ForegroundColor = (Color)colorBoxForeground.SelectedItem; entry.BackgroundColor = (Color)colorBoxBackground.SelectedItem; @@ -679,7 +679,7 @@ private void SelectGroup(int index) private void StartEditEntry() { - HighlightEntry entry = (HighlightEntry)listBoxHighlight.SelectedItem; + var entry = (HighlightEntry)listBoxHighlight.SelectedItem; if (entry != null) { diff --git a/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindow.cs b/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindow.cs index fba25456..55e54962 100644 --- a/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindow.cs +++ b/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindow.cs @@ -90,13 +90,13 @@ public LogTabWindow (string[] fileNames, int instanceNumber, bool showInstanceNu Rectangle led = new(0, 0, 8, 2); - for (int i = 0; i < _leds.Length; ++i) + for (var i = 0; i < _leds.Length; ++i) { _leds[i] = led; led.Offset(0, led.Height + 0); } - int grayAlpha = 50; + var grayAlpha = 50; _ledBrushes[0] = new SolidBrush(Color.FromArgb(255, 220, 0, 0)); _ledBrushes[1] = new SolidBrush(Color.FromArgb(255, 220, 220, 0)); @@ -124,7 +124,7 @@ public LogTabWindow (string[] fileNames, int instanceNumber, bool showInstanceNu host.Padding = new Padding(20, 0, 0, 0); host.BackColor = Color.FromKnownColor(KnownColor.Transparent); - int index = buttonToolStrip.Items.IndexOfKey("toolStripButtonTail"); + var index = buttonToolStrip.Items.IndexOfKey("toolStripButtonTail"); toolStripEncodingASCIIItem.Text = Encoding.ASCII.HeaderName; toolStripEncodingANSIItem.Text = Encoding.Default.HeaderName; @@ -142,10 +142,10 @@ public LogTabWindow (string[] fileNames, int instanceNumber, bool showInstanceNu loadProgessBar.Visible = false; // get a reference to the current assembly - Assembly a = Assembly.GetExecutingAssembly(); + var a = Assembly.GetExecutingAssembly(); // get a list of resource names from the manifest - string[] resNames = a.GetManifestResourceNames(); + var resNames = a.GetManifestResourceNames(); Bitmap bmp = Resources.Resources.Deceased; _deadIcon = Icon.FromHandle(bmp.GetHicon()); diff --git a/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindowEventHandlers.cs b/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindowEventHandlers.cs index b515cdcb..034172db 100644 --- a/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindowEventHandlers.cs +++ b/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindowEventHandlers.cs @@ -14,7 +14,8 @@ using WeifenLuo.WinFormsUI.Docking; namespace LogExpert.UI.Controls.LogTabWindow; -partial class LogTabWindow + +public partial class LogTabWindow { #region Events handler @@ -44,7 +45,7 @@ private void OnLogTabWindowLoad (object sender, EventArgs e) { List tmpList = ObjectClone.Clone(ConfigManager.Settings.lastOpenFilesList); - foreach (string name in tmpList) + foreach (var name in tmpList) { if (string.IsNullOrEmpty(name) == false) { @@ -126,7 +127,7 @@ private void OnHistoryItemClicked (object sender, ToolStripItemClickedEventArgs private void OnLogWindowDisposed (object sender, EventArgs e) { - LogWindow.LogWindow logWindow = sender as LogWindow.LogWindow; + var logWindow = sender as LogWindow.LogWindow; if (sender == CurrentLogWindow) { @@ -218,7 +219,7 @@ private void OnGoToLineToolStripMenuItemClick (object sender, EventArgs e) DialogResult res = dlg.ShowDialog(); if (res == DialogResult.OK) { - int line = dlg.Line - 1; + var line = dlg.Line - 1; if (line >= 0) { CurrentLogWindow.GotoLine(line); @@ -244,9 +245,9 @@ private void OnOpenToolStripMenuItemClick (object sender, EventArgs e) private void OnLogTabWindowDragEnter (object sender, DragEventArgs e) { #if DEBUG - string[] formats = e.Data.GetFormats(); - string s = "Dragging something over LogExpert. Formats: "; - foreach (string format in formats) + var formats = e.Data.GetFormats(); + var s = "Dragging something over LogExpert. Formats: "; + foreach (var format in formats) { s += format; s += " , "; @@ -271,9 +272,9 @@ private void OnLogWindowDragOver (object sender, DragEventArgs e) private void OnLogWindowDragDrop (object sender, DragEventArgs e) { #if DEBUG - string[] formats = e.Data.GetFormats(); - string s = "Dropped formats: "; - foreach (string format in formats) + var formats = e.Data.GetFormats(); + var s = "Dropped formats: "; + foreach (var format in formats) { s += format; s += " , "; @@ -284,7 +285,7 @@ private void OnLogWindowDragDrop (object sender, DragEventArgs e) if (e.Data.GetDataPresent(DataFormats.FileDrop)) { - object o = e.Data.GetData(DataFormats.FileDrop); + var o = e.Data.GetData(DataFormats.FileDrop); if (o is string[] names) { LoadFiles(names, (e.KeyState & 4) == 4); // (shift pressed?) @@ -416,7 +417,7 @@ private void OnFileSizeChanged (object sender, LogEventArgs e) { if (sender.GetType().IsAssignableFrom(typeof(LogWindow.LogWindow))) { - int diff = e.LineCount - e.PrevLineCount; + var diff = e.LineCount - e.PrevLineCount; if (diff < 0) { return; @@ -488,7 +489,7 @@ private void OnTailFollowed (object sender, EventArgs e) { if (dockPanel.ActiveContent == sender) { - LogWindowData data = ((LogWindow.LogWindow)sender).Tag as LogWindowData; + var data = ((LogWindow.LogWindow)sender).Tag as LogWindowData; data.dirty = false; Icon icon = GetIcon(data.diffSum, data); BeginInvoke(new SetTabIconDelegate(SetTabIcon), (LogWindow.LogWindow)sender, icon); @@ -500,7 +501,7 @@ private void OnLogWindowSyncModeChanged (object sender, SyncModeEventArgs e) { if (!Disposing) { - LogWindowData data = ((LogWindow.LogWindow)sender).Tag as LogWindowData; + var data = ((LogWindow.LogWindow)sender).Tag as LogWindowData; data.syncMode = e.IsTimeSynced ? 1 : 0; Icon icon = GetIcon(data.diffSum, data); BeginInvoke(new SetTabIconDelegate(SetTabIcon), (LogWindow.LogWindow)sender, icon); @@ -555,7 +556,7 @@ private void OnReloadToolStripMenuItemClick (object sender, EventArgs e) { if (CurrentLogWindow != null) { - LogWindowData data = CurrentLogWindow.Tag as LogWindowData; + var data = CurrentLogWindow.Tag as LogWindowData; Icon icon = GetIcon(0, data); BeginInvoke(new SetTabIconDelegate(SetTabIcon), CurrentLogWindow, icon); CurrentLogWindow.Reload(); @@ -692,9 +693,9 @@ private void OnCloseAllTabsToolStripMenuItemClick (object sender, EventArgs e) private void OnTabColorToolStripMenuItemClick (object sender, EventArgs e) { - LogWindow.LogWindow logWindow = dockPanel.ActiveContent as LogWindow.LogWindow; + var logWindow = dockPanel.ActiveContent as LogWindow.LogWindow; - LogWindowData data = logWindow.Tag as LogWindowData; + var data = logWindow.Tag as LogWindowData; if (data == null) { @@ -746,15 +747,15 @@ private void OnSaveProjectToolStripMenuItemClick (object sender, EventArgs e) if (dlg.ShowDialog() == DialogResult.OK) { - string fileName = dlg.FileName; + var fileName = dlg.FileName; List fileNames = []; lock (_logWindowList) { foreach (DockContent content in dockPanel.Contents) { - LogWindow.LogWindow logWindow = content as LogWindow.LogWindow; - string persistenceFileName = logWindow?.SavePersistenceData(true); + var logWindow = content as LogWindow.LogWindow; + var persistenceFileName = logWindow?.SavePersistenceData(true); if (persistenceFileName != null) { fileNames.Add(persistenceFileName); @@ -763,8 +764,8 @@ private void OnSaveProjectToolStripMenuItemClick (object sender, EventArgs e) } ProjectData projectData = new(); - projectData.memberList = fileNames; - projectData.tabLayoutXml = SaveLayout(); + projectData.MemberList = fileNames; + projectData.TabLayoutXml = SaveLayout(); ProjectPersister.SaveProjectData(fileName, projectData); } } @@ -777,7 +778,7 @@ private void OnLoadProjectToolStripMenuItemClick (object sender, EventArgs e) if (dlg.ShowDialog() == DialogResult.OK) { - string projectFileName = dlg.FileName; + var projectFileName = dlg.FileName; LoadProject(projectFileName, true); } } @@ -792,13 +793,13 @@ private void OnToolStripButtonBubblesClick (object sender, EventArgs e) private void OnCopyPathToClipboardToolStripMenuItemClick (object sender, EventArgs e) { - LogWindow.LogWindow logWindow = dockPanel.ActiveContent as LogWindow.LogWindow; + var logWindow = dockPanel.ActiveContent as LogWindow.LogWindow; Clipboard.SetText(logWindow.Title); } private void OnFindInExplorerToolStripMenuItemClick (object sender, EventArgs e) { - LogWindow.LogWindow logWindow = dockPanel.ActiveContent as LogWindow.LogWindow; + var logWindow = dockPanel.ActiveContent as LogWindow.LogWindow; Process explorer = new(); explorer.StartInfo.FileName = "explorer.exe"; diff --git a/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindowPrivate.cs b/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindowPrivate.cs index d6b6c722..173763fd 100644 --- a/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindowPrivate.cs +++ b/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindowPrivate.cs @@ -1176,7 +1176,7 @@ private void SetTabColor (LogWindow.LogWindow logWindow, Color color) private void LoadProject (string projectFileName, bool restoreLayout) { ProjectData projectData = ProjectPersister.LoadProjectData(projectFileName); - var hasLayoutData = projectData.tabLayoutXml != null; + var hasLayoutData = projectData.TabLayoutXml != null; if (hasLayoutData && restoreLayout && _logWindowList.Count > 0) { @@ -1200,7 +1200,7 @@ private void LoadProject (string projectFileName, bool restoreLayout) if (projectData != null) { - foreach (var fileName in projectData.memberList) + foreach (var fileName in projectData.MemberList) { if (hasLayoutData) { @@ -1217,7 +1217,7 @@ private void LoadProject (string projectFileName, bool restoreLayout) // Re-creating tool (non-document) windows is needed because the DockPanel control would throw strange errors DestroyToolWindows(); InitToolWindows(); - RestoreLayout(projectData.tabLayoutXml); + RestoreLayout(projectData.TabLayoutXml); } } } @@ -1233,10 +1233,10 @@ private void ApplySelectedHighlightGroup () private void FillToolLauncherBar () { char[] labels = - { + [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' - }; + ]; toolsToolStripMenuItem.DropDownItems.Clear(); toolsToolStripMenuItem.DropDownItems.Add(configureToolStripMenuItem); toolsToolStripMenuItem.DropDownItems.Add(configureToolStripSeparator); diff --git a/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindowPublic.cs b/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindowPublic.cs index d264fbe3..a324dec3 100644 --- a/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindowPublic.cs +++ b/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindowPublic.cs @@ -36,7 +36,7 @@ public LogWindow.LogWindow AddFilterTab (FilterPipe pipe, string title, ILogLine ); tip.AutomaticDelay = 10; tip.AutoPopDelay = 5000; - LogWindowData data = logWin.Tag as LogWindowData; + var data = logWin.Tag as LogWindowData; data.toolTip = tip; } @@ -50,7 +50,7 @@ public LogWindow.LogWindow AddFileTabDeferred (string givenFileName, bool isTemp public LogWindow.LogWindow AddFileTab (string givenFileName, bool isTempFile, string title, bool forcePersistenceLoading, ILogLineColumnizer preProcessColumnizer, bool doNotAddToDockPanel = false) { - string logFileName = FindFilenameForSettings(givenFileName); + var logFileName = FindFilenameForSettings(givenFileName); LogWindow.LogWindow win = FindWindowForFile(logFileName); if (win != null) { @@ -86,7 +86,7 @@ public LogWindow.LogWindow AddFileTab (string givenFileName, bool isTempFile, st AddToFileHistory(givenFileName); } - LogWindowData data = logWindow.Tag as LogWindowData; + var data = logWindow.Tag as LogWindowData; data.color = _defaultTabColor; SetTabColor(logWindow, _defaultTabColor); //data.tabPage.BorderColor = this.defaultTabBorderColor; @@ -183,7 +183,7 @@ public ILogLineColumnizer GetColumnizerHistoryEntry (string fileName) public void SwitchTab (bool shiftPressed) { - int index = dockPanel.Contents.IndexOf(dockPanel.ActiveContent); + var index = dockPanel.Contents.IndexOf(dockPanel.ActiveContent); if (shiftPressed) { index--; @@ -303,7 +303,7 @@ public void SetForeground () // called from LogWindow when follow tail was changed public void FollowTailChanged (LogWindow.LogWindow logWindow, bool isEnabled, bool offByTrigger) { - LogWindowData data = logWindow.Tag as LogWindowData; + var data = logWindow.Tag as LogWindowData; if (data == null) { return; diff --git a/src/LogExpert.UI/Dialogs/LogTabWindow/SettingsDialog.cs b/src/LogExpert.UI/Dialogs/LogTabWindow/SettingsDialog.cs index 03035118..0d5308c7 100644 --- a/src/LogExpert.UI/Dialogs/LogTabWindow/SettingsDialog.cs +++ b/src/LogExpert.UI/Dialogs/LogTabWindow/SettingsDialog.cs @@ -273,13 +273,13 @@ private void FillColumnizerForToolsList() private void FillColumnizerForToolsList(ComboBox comboBox, string columnizerName) { - int selIndex = 0; + var selIndex = 0; comboBox.Items.Clear(); IList columnizers = PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers; foreach (ILogLineColumnizer columnizer in columnizers) { - int index = comboBox.Items.Add(columnizer.GetName()); + var index = comboBox.Items.Add(columnizer.GetName()); if (columnizer.GetName().Equals(columnizerName)) { selIndex = index; @@ -296,10 +296,10 @@ private void FillColumnizerList() { dataGridViewColumnizer.Rows.Clear(); - DataGridViewComboBoxColumn comboColumn = (DataGridViewComboBoxColumn)dataGridViewColumnizer.Columns[1]; + var comboColumn = (DataGridViewComboBoxColumn)dataGridViewColumnizer.Columns[1]; comboColumn.Items.Clear(); - DataGridViewTextBoxColumn textColumn = (DataGridViewTextBoxColumn)dataGridViewColumnizer.Columns[0]; + var textColumn = (DataGridViewTextBoxColumn)dataGridViewColumnizer.Columns[0]; IList columnizers = PluginRegistry.PluginRegistry.Instance.RegisteredColumnizers; @@ -330,11 +330,11 @@ private void FillColumnizerList() dataGridViewColumnizer.Rows.Add(row); } - int count = dataGridViewColumnizer.RowCount; + var count = dataGridViewColumnizer.RowCount; if (count > 0 && !dataGridViewColumnizer.Rows[count - 1].IsNewRow) { - DataGridViewComboBoxCell comboCell = (DataGridViewComboBoxCell)dataGridViewColumnizer.Rows[count - 1].Cells[1]; + var comboCell = (DataGridViewComboBoxCell)dataGridViewColumnizer.Rows[count - 1].Cells[1]; comboCell.Value = comboCell.Items[0]; } } @@ -343,11 +343,11 @@ private void FillHighlightMaskList() { dataGridViewHighlightMask.Rows.Clear(); - DataGridViewComboBoxColumn comboColumn = (DataGridViewComboBoxColumn)dataGridViewHighlightMask.Columns[1]; + var comboColumn = (DataGridViewComboBoxColumn)dataGridViewHighlightMask.Columns[1]; comboColumn.Items.Clear(); //TODO Remove if not necessary - DataGridViewTextBoxColumn textColumn = (DataGridViewTextBoxColumn)dataGridViewHighlightMask.Columns[0]; + var textColumn = (DataGridViewTextBoxColumn)dataGridViewHighlightMask.Columns[0]; foreach (HighlightGroup group in (IList)_logTabWin.HighlightGroupList) { @@ -376,11 +376,11 @@ private void FillHighlightMaskList() dataGridViewHighlightMask.Rows.Add(row); } - int count = dataGridViewHighlightMask.RowCount; + var count = dataGridViewHighlightMask.RowCount; if (count > 0 && !dataGridViewHighlightMask.Rows[count - 1].IsNewRow) { - DataGridViewComboBoxCell comboCell = + var comboCell = (DataGridViewComboBoxCell)dataGridViewHighlightMask.Rows[count - 1].Cells[1]; comboCell.Value = comboCell.Items[0]; } @@ -518,7 +518,7 @@ private void GetToolListBoxData() GetCurrentToolValues(); Preferences.toolEntries.Clear(); - for (int i = 0; i < listBoxTools.Items.Count; ++i) + for (var i = 0; i < listBoxTools.Items.Count; ++i) { Preferences.toolEntries.Add(listBoxTools.Items[i] as ToolEntry); (listBoxTools.Items[i] as ToolEntry).isFavourite = listBoxTools.GetItemChecked(i); @@ -701,7 +701,7 @@ private void OnBtnArgClick(object sender, EventArgs e) //TODO Remove or refactor this function private void OnDataGridViewColumnizerRowsAdded(object sender, DataGridViewRowsAddedEventArgs e) { - DataGridViewComboBoxCell comboCell = (DataGridViewComboBoxCell)dataGridViewColumnizer.Rows[e.RowIndex].Cells[1]; + var comboCell = (DataGridViewComboBoxCell)dataGridViewColumnizer.Rows[e.RowIndex].Cells[1]; if (comboCell.Items.Count > 0) { // comboCell.Value = comboCell.Items[0]; @@ -712,7 +712,7 @@ private void OnBtnDeleteClick(object sender, EventArgs e) { if (dataGridViewColumnizer.CurrentRow != null && !dataGridViewColumnizer.CurrentRow.IsNewRow) { - int index = dataGridViewColumnizer.CurrentRow.Index; + var index = dataGridViewColumnizer.CurrentRow.Index; dataGridViewColumnizer.EndEdit(); dataGridViewColumnizer.Rows.RemoveAt(index); } @@ -763,7 +763,7 @@ private void OnListBoxPluginSelectedIndexChanged(object sender, EventArgs e) { _selectedPlugin?.HideConfigForm(); - object o = listBoxPlugin.SelectedItem; + var o = listBoxPlugin.SelectedItem; if (o != null) { @@ -883,12 +883,12 @@ private void OnListBoxToolSelectedIndexChanged(object sender, EventArgs e) private void OnBtnToolUpClick(object sender, EventArgs e) { - int i = listBoxTools.SelectedIndex; + var i = listBoxTools.SelectedIndex; if (i > 0) { - bool isChecked = listBoxTools.GetItemChecked(i); - object item = listBoxTools.Items[i]; + var isChecked = listBoxTools.GetItemChecked(i); + var item = listBoxTools.Items[i]; listBoxTools.Items.RemoveAt(i); i--; listBoxTools.Items.Insert(i, item); @@ -899,12 +899,12 @@ private void OnBtnToolUpClick(object sender, EventArgs e) private void OnBtnToolDownClick(object sender, EventArgs e) { - int i = listBoxTools.SelectedIndex; + var i = listBoxTools.SelectedIndex; if (i < listBoxTools.Items.Count - 1) { - bool isChecked = listBoxTools.GetItemChecked(i); - object item = listBoxTools.Items[i]; + var isChecked = listBoxTools.GetItemChecked(i); + var item = listBoxTools.Items[i]; listBoxTools.Items.RemoveAt(i); i++; listBoxTools.Items.Insert(i, item); @@ -921,7 +921,7 @@ private void OnBtnToolAddClick(object sender, EventArgs e) private void OnToolDeleteButtonClick(object sender, EventArgs e) { - int i = listBoxTools.SelectedIndex; + var i = listBoxTools.SelectedIndex; if (i < listBoxTools.Items.Count && i >= 0) { @@ -944,7 +944,7 @@ private void OnBtnIconClick(object sender, EventArgs e) { if (_selectedTool != null) { - string iconFile = _selectedTool.iconFile; + var iconFile = _selectedTool.iconFile; if (Util.IsNullOrSpaces(iconFile)) { @@ -974,7 +974,7 @@ private void OnBtnWorkingDirClick(object sender, EventArgs e) private void OnMultiFilePatternTextChanged(object sender, EventArgs e) { - string pattern = textBoxMultifilePattern.Text; + var pattern = textBoxMultifilePattern.Text; upDownMultifileDays.Enabled = pattern.Contains("$D"); } diff --git a/src/LogExpert.UI/Dialogs/OpenUriDialog.cs b/src/LogExpert.UI/Dialogs/OpenUriDialog.cs index fc079883..290a2471 100644 --- a/src/LogExpert.UI/Dialogs/OpenUriDialog.cs +++ b/src/LogExpert.UI/Dialogs/OpenUriDialog.cs @@ -39,7 +39,7 @@ private void OnOpenUriDialogLoad(object sender, EventArgs e) if (UriHistory != null) { cmbUri.Items.Clear(); - foreach (string uri in UriHistory) + foreach (var uri in UriHistory) { cmbUri.Items.Add(uri); } @@ -50,7 +50,7 @@ private void OnBtnOkClick(object sender, EventArgs e) { UriHistory = []; - foreach (object item in cmbUri.Items) + foreach (var item in cmbUri.Items) { UriHistory.Add(item.ToString()); } diff --git a/src/LogExpert.UI/Dialogs/ParamRequesterDialog.cs b/src/LogExpert.UI/Dialogs/ParamRequesterDialog.cs index 8953650d..26d38846 100644 --- a/src/LogExpert.UI/Dialogs/ParamRequesterDialog.cs +++ b/src/LogExpert.UI/Dialogs/ParamRequesterDialog.cs @@ -44,7 +44,7 @@ private void ParamRequesterDialog_Shown(object sender, EventArgs e) if (Values != null) { - foreach (string value in Values) + foreach (var value in Values) { comboBoxValue.Items.Add(value); } diff --git a/src/LogExpert.UI/Dialogs/RegexHelperDialog.cs b/src/LogExpert.UI/Dialogs/RegexHelperDialog.cs index 36c2749a..d564884b 100644 --- a/src/LogExpert.UI/Dialogs/RegexHelperDialog.cs +++ b/src/LogExpert.UI/Dialogs/RegexHelperDialog.cs @@ -108,7 +108,7 @@ private void OnCaseSensitiveCheckBoxCheckedChanged(object sender, EventArgs e) private void OnButtonOkClick(object sender, EventArgs e) { - string text = comboBoxRegex.Text; + var text = comboBoxRegex.Text; comboBoxRegex.Items.Remove(text); comboBoxRegex.Items.Insert(0, text); diff --git a/src/LogExpert.UI/Dialogs/SearchDialog.cs b/src/LogExpert.UI/Dialogs/SearchDialog.cs index b74ee792..e4542dc5 100644 --- a/src/LogExpert.UI/Dialogs/SearchDialog.cs +++ b/src/LogExpert.UI/Dialogs/SearchDialog.cs @@ -61,7 +61,7 @@ private void OnSearchDialogLoad(object? sender, EventArgs e) checkBoxRegex.Checked = SearchParams.IsRegex; checkBoxCaseSensitive.Checked = SearchParams.IsCaseSensitive; - foreach (string item in SearchParams.HistoryList) + foreach (var item in SearchParams.HistoryList) { comboBoxSearchFor.Items.Add(item); } diff --git a/src/LogExpert.UI/Dialogs/ToolArgsDialog.cs b/src/LogExpert.UI/Dialogs/ToolArgsDialog.cs index da95f186..60271fdf 100644 --- a/src/LogExpert.UI/Dialogs/ToolArgsDialog.cs +++ b/src/LogExpert.UI/Dialogs/ToolArgsDialog.cs @@ -81,7 +81,7 @@ private void OnButtonTestClick(object sender, EventArgs e) if (line != null && info != null) { ArgParser parser = new(textBoxArguments.Text); - string args = parser.BuildArgs(line, logTabWin.CurrentLogWindow.GetRealLineNum() + 1, info, this); + var args = parser.BuildArgs(line, logTabWin.CurrentLogWindow.GetRealLineNum() + 1, info, this); labelTestResult.Text = args; } } diff --git a/src/LogExpert.UI/Entities/ArgParser.cs b/src/LogExpert.UI/Entities/ArgParser.cs index 3b187342..215a1981 100644 --- a/src/LogExpert.UI/Entities/ArgParser.cs +++ b/src/LogExpert.UI/Entities/ArgParser.cs @@ -1,156 +1,154 @@ -using System; -using System.Text; +using System.Text; using System.Text.RegularExpressions; -using System.Windows.Forms; using LogExpert.Core.Classes; using LogExpert.Dialogs; -namespace LogExpert.Classes +namespace LogExpert.Classes; + +internal class ArgParser { - internal class ArgParser - { - #region Fields + #region Fields - private readonly string argLine; + private readonly string argLine; - #endregion + #endregion - #region cTor + #region cTor - public ArgParser(string argTemplate) - { - argLine = argTemplate; - } + public ArgParser (string argTemplate) + { + argLine = argTemplate; + } - #endregion + #endregion - #region Public methods + #region Public methods - public string BuildArgs(ILogLine logLine, int lineNum, ILogFileInfo logFileInfo, Form parent) + public string BuildArgs (ILogLine logLine, int lineNum, ILogFileInfo logFileInfo, Form parent) + { + StringBuilder builder = new(argLine); + builder.Replace("%L", "" + lineNum); + builder.Replace("%P", logFileInfo.DirectoryName); + builder.Replace("%N", logFileInfo.FileName); + builder.Replace("%F", logFileInfo.FullName); + builder.Replace("%E", Util.GetExtension(logFileInfo.FileName)); + var stripped = Util.StripExtension(logFileInfo.FileName); + builder.Replace("%M", stripped); + + builder.Replace("%URI", logFileInfo.Uri.AbsoluteUri); + var user = logFileInfo.Uri.UserInfo; + if (user.Contains(":")) + { + user = user.Substring(0, user.IndexOf(':')); + } + builder.Replace("%S", user); + builder.Replace("%R", logFileInfo.Uri.PathAndQuery); + builder.Replace("%H", logFileInfo.Uri.Host); + builder.Replace("%T", logFileInfo.Uri.Port.ToString()); + + var sPos = 0; + string reg; + string replace; + do { - StringBuilder builder = new(argLine); - builder.Replace("%L", "" + lineNum); - builder.Replace("%P", logFileInfo.DirectoryName); - builder.Replace("%N", logFileInfo.FileName); - builder.Replace("%F", logFileInfo.FullName); - builder.Replace("%E", Util.GetExtension(logFileInfo.FileName)); - string stripped = Util.StripExtension(logFileInfo.FileName); - builder.Replace("%M", stripped); - - builder.Replace("%URI", logFileInfo.Uri.AbsoluteUri); - string user = logFileInfo.Uri.UserInfo; - if (user.Contains(":")) + reg = GetNextGroup(builder, ref sPos); + replace = GetNextGroup(builder, ref sPos); + if (reg != null && replace != null) { - user = user.Substring(0, user.IndexOf(':')); + var result = Regex.Replace(logLine.FullLine, reg, replace); + builder.Insert(sPos, result); } - builder.Replace("%S", user); - builder.Replace("%R", logFileInfo.Uri.PathAndQuery); - builder.Replace("%H", logFileInfo.Uri.Host); - builder.Replace("%T", logFileInfo.Uri.Port.ToString()); - - int sPos = 0; - string reg; - string replace; - do - { - reg = GetNextGroup(builder, ref sPos); - replace = GetNextGroup(builder, ref sPos); - if (reg != null && replace != null) - { - string result = Regex.Replace(logLine.FullLine, reg, replace); - builder.Insert(sPos, result); - } - } while (replace != null); + } while (replace != null); - int i = 0; - while (i < builder.Length) + var i = 0; + while (i < builder.Length) + { + // ?"Pinpad-type?"(thales,dione) + if (builder[i] == '?') { - // ?"Pinpad-type?"(thales,dione) - if (builder[i] == '?') + var end = i; + var ask = "Parameter"; + if (builder[i + 1] == '"') { - int end = i; - string ask = "Parameter"; - if (builder[i + 1] == '"') + end = builder.ToString().IndexOf('"', i + 2); + if (end == -1) { - end = builder.ToString().IndexOf('"', i + 2); - if (end == -1) - { - end = builder.Length - 1; - } - ask = builder.ToString().Substring(i + 2, end - i - 2); + end = builder.Length - 1; } - string[] values = null; - if (builder[end + 1] == '(') + ask = builder.ToString().Substring(i + 2, end - i - 2); + } + string[] values = null; + if (builder[end + 1] == '(') + { + var end2 = builder.ToString().IndexOf(')'); + if (end2 == -1) { - int end2 = builder.ToString().IndexOf(')'); - if (end2 == -1) - { - end2 = builder.Length - 1; - } - string valueStr = builder.ToString().Substring(end + 2, end2 - end - 2); - values = valueStr.Split(new char[] { ',' }, StringSplitOptions.None); - end = end2; + end2 = builder.Length - 1; } + var valueStr = builder.ToString().Substring(end + 2, end2 - end - 2); + values = valueStr.Split([','], StringSplitOptions.None); + end = end2; + } - ParamRequesterDialog dlg = new(); - dlg.ParamName = ask; - dlg.Values = values; - DialogResult res = dlg.ShowDialog(parent); - if (res == DialogResult.OK) - { - builder.Remove(i, end - i + 1); - builder.Insert(i, dlg.ParamValue); - } - else if (res == DialogResult.Cancel || res == DialogResult.Abort) - { - return null; - } + ParamRequesterDialog dlg = new(); + dlg.ParamName = ask; + dlg.Values = values; + DialogResult res = dlg.ShowDialog(parent); + + if (res == DialogResult.OK) + { + builder.Remove(i, end - i + 1); + builder.Insert(i, dlg.ParamValue); + } + else if (res == DialogResult.Cancel || res == DialogResult.Abort) + { + return null; } - ++i; } - return builder.ToString(); + ++i; } - #endregion + return builder.ToString(); + } + + #endregion - #region Private Methods + #region Private Methods - private string GetNextGroup(StringBuilder builder, ref int sPos) + private string GetNextGroup (StringBuilder builder, ref int sPos) + { + int ePos; + while (sPos < builder.Length) { - int count = 0; - int ePos; - while (sPos < builder.Length) + if (builder[sPos] == '{') { - if (builder[sPos] == '{') + ePos = sPos + 1; + var count = 1; + while (ePos < builder.Length) { - ePos = sPos + 1; - count = 1; - while (ePos < builder.Length) + if (builder[ePos] == '{') + { + count++; + } + if (builder[ePos] == '}') { - if (builder[ePos] == '{') - { - count++; - } - if (builder[ePos] == '}') - { - count--; - } - if (count == 0) - { - string reg = builder.ToString(sPos + 1, ePos - sPos - 1); - builder.Remove(sPos, ePos - sPos + 1); - return reg; - } - ePos++; + count--; } + if (count == 0) + { + var reg = builder.ToString(sPos + 1, ePos - sPos - 1); + builder.Remove(sPos, ePos - sPos + 1); + return reg; + } + ePos++; } - sPos++; } - return null; + sPos++; } - - #endregion + return null; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.UI/Entities/PaintHelper.cs b/src/LogExpert.UI/Entities/PaintHelper.cs index eeb499e6..6c795af4 100644 --- a/src/LogExpert.UI/Entities/PaintHelper.cs +++ b/src/LogExpert.UI/Entities/PaintHelper.cs @@ -7,483 +7,482 @@ using LogExpert.UI.Interface; using NLog; -namespace LogExpert.UI.Entities +namespace LogExpert.UI.Entities; + +//TOOD: This whole class should be refactored and rethought +//TODO: This class should not knoow ConfigManager? +internal static class PaintHelper { - //TOOD: This whole class should be refactored and rethought - //TODO: This class should not knoow ConfigManager? - internal static class PaintHelper - { - #region Fields + #region Fields - private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); + private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); - //TODO Make configurable - private static Color _bookmarkColor = Color.FromArgb(165, 200, 225); + //TODO Make configurable + private static Color _bookmarkColor = Color.FromArgb(165, 200, 225); - #endregion + #endregion - #region Properties - public static IConfigManager ConfigManager { get; set; } - private static Preferences Preferences => ConfigManager.Settings.Preferences; + #region Properties + public static IConfigManager ConfigManager { get; set; } + private static Preferences Preferences => ConfigManager.Settings.Preferences; - #endregion + #endregion - #region Public methods + #region Public methods - public static void CellPainting(ILogPaintContextUI logPaintCtx, BufferedDataGridView gridView, int rowIndex, - DataGridViewCellPaintingEventArgs e) + public static void CellPainting(ILogPaintContextUI logPaintCtx, BufferedDataGridView gridView, int rowIndex, + DataGridViewCellPaintingEventArgs e) + { + if (rowIndex < 0 || e.ColumnIndex < 0) + { + e.Handled = false; + return; + } + ILogLine line = logPaintCtx.GetLogLine(rowIndex); + if (line != null) { - if (rowIndex < 0 || e.ColumnIndex < 0) + HighlightEntry entry = logPaintCtx.FindHighlightEntry(line, true); + e.Graphics.SetClip(e.CellBounds); + if ((e.State & DataGridViewElementStates.Selected) == DataGridViewElementStates.Selected) { - e.Handled = false; - return; + Color backColor = e.CellStyle.SelectionBackColor; + Brush brush; + if (gridView.Focused) + { + brush = new SolidBrush(e.CellStyle.SelectionBackColor); + } + else + { + var color = Color.FromArgb(255, 170, 170, 170); + brush = new SolidBrush(color); + } + e.Graphics.FillRectangle(brush, e.CellBounds); + brush.Dispose(); } - ILogLine line = logPaintCtx.GetLogLine(rowIndex); - if (line != null) + else { - HighlightEntry entry = logPaintCtx.FindHighlightEntry(line, true); - e.Graphics.SetClip(e.CellBounds); - if ((e.State & DataGridViewElementStates.Selected) == DataGridViewElementStates.Selected) + Color bgColor = ColorMode.DockBackgroundColor; + if (!DebugOptions.DisableWordHighlight) { - Color backColor = e.CellStyle.SelectionBackColor; - Brush brush; - if (gridView.Focused) - { - brush = new SolidBrush(e.CellStyle.SelectionBackColor); - } - else + if (entry != null) { - Color color = Color.FromArgb(255, 170, 170, 170); - brush = new SolidBrush(color); + bgColor = entry.BackgroundColor; } - e.Graphics.FillRectangle(brush, e.CellBounds); - brush.Dispose(); } else { - Color bgColor = ColorMode.DockBackgroundColor; - if (!DebugOptions.DisableWordHighlight) + if (entry != null) { - if (entry != null) - { - bgColor = entry.BackgroundColor; - } + bgColor = entry.BackgroundColor; } - else - { - if (entry != null) - { - bgColor = entry.BackgroundColor; - } - } - e.CellStyle.BackColor = bgColor; - e.PaintBackground(e.ClipBounds, false); } + e.CellStyle.BackColor = bgColor; + e.PaintBackground(e.ClipBounds, false); + } - if (DebugOptions.DisableWordHighlight) - { - e.PaintContent(e.CellBounds); - } - else - { - PaintCell(logPaintCtx, e, gridView, false, entry); - } + if (DebugOptions.DisableWordHighlight) + { + e.PaintContent(e.CellBounds); + } + else + { + PaintCell(logPaintCtx, e, gridView, false, entry); + } - if (e.ColumnIndex == 0) + if (e.ColumnIndex == 0) + { + Bookmark bookmark = logPaintCtx.GetBookmarkForLine(rowIndex); + if (bookmark != null) { - Bookmark bookmark = logPaintCtx.GetBookmarkForLine(rowIndex); - if (bookmark != null) + Rectangle r; // = new Rectangle(e.CellBounds.Left + 2, e.CellBounds.Top + 2, 6, 6); + r = e.CellBounds; + r.Inflate(-2, -2); + Brush brush = new SolidBrush(logPaintCtx.BookmarkColor); + e.Graphics.FillRectangle(brush, r); + brush.Dispose(); + if (bookmark.Text.Length > 0) { - Rectangle r; // = new Rectangle(e.CellBounds.Left + 2, e.CellBounds.Top + 2, 6, 6); - r = e.CellBounds; - r.Inflate(-2, -2); - Brush brush = new SolidBrush(logPaintCtx.BookmarkColor); - e.Graphics.FillRectangle(brush, r); - brush.Dispose(); - if (bookmark.Text.Length > 0) - { - StringFormat format = new(); - format.LineAlignment = StringAlignment.Center; - format.Alignment = StringAlignment.Center; - Brush brush2 = new SolidBrush(Color.FromArgb(255, 190, 100, 0)); - Font font = logPaintCtx.MonospacedFont; - e.Graphics.DrawString("i", font, brush2, new RectangleF(r.Left, r.Top, r.Width, r.Height), - format); - brush2.Dispose(); - } + StringFormat format = new(); + format.LineAlignment = StringAlignment.Center; + format.Alignment = StringAlignment.Center; + Brush brush2 = new SolidBrush(Color.FromArgb(255, 190, 100, 0)); + Font font = logPaintCtx.MonospacedFont; + e.Graphics.DrawString("i", font, brush2, new RectangleF(r.Left, r.Top, r.Width, r.Height), + format); + brush2.Dispose(); } } - - e.Paint(e.CellBounds, DataGridViewPaintParts.Border); - e.Handled = true; } - } - public static DataGridViewTextBoxColumn CreateMarkerColumn() - { - DataGridViewTextBoxColumn markerColumn = new(); - markerColumn.HeaderText = ""; - markerColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.NotSet; - markerColumn.Resizable = DataGridViewTriState.False; - markerColumn.DividerWidth = 1; - markerColumn.ReadOnly = true; - markerColumn.SortMode = DataGridViewColumnSortMode.NotSortable; - - return markerColumn; + e.Paint(e.CellBounds, DataGridViewPaintParts.Border); + e.Handled = true; } + } - public static DataGridViewTextBoxColumn CreateLineNumberColumn() + public static DataGridViewTextBoxColumn CreateMarkerColumn() + { + DataGridViewTextBoxColumn markerColumn = new(); + markerColumn.HeaderText = ""; + markerColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.NotSet; + markerColumn.Resizable = DataGridViewTriState.False; + markerColumn.DividerWidth = 1; + markerColumn.ReadOnly = true; + markerColumn.SortMode = DataGridViewColumnSortMode.NotSortable; + + return markerColumn; + } + + public static DataGridViewTextBoxColumn CreateLineNumberColumn() + { + DataGridViewTextBoxColumn lineNumberColumn = new(); + lineNumberColumn.HeaderText = "Line"; + lineNumberColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.NotSet; + lineNumberColumn.Resizable = DataGridViewTriState.NotSet; + lineNumberColumn.DividerWidth = 1; + lineNumberColumn.ReadOnly = true; + lineNumberColumn.SortMode = DataGridViewColumnSortMode.NotSortable; + + return lineNumberColumn; + } + + public static DataGridViewColumn CreateTitleColumn(string colName) + { + DataGridViewColumn titleColumn = new LogTextColumn(); + titleColumn.HeaderText = colName; + titleColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.NotSet; + titleColumn.Resizable = DataGridViewTriState.NotSet; + titleColumn.DividerWidth = 1; + titleColumn.SortMode = DataGridViewColumnSortMode.NotSortable; + + return titleColumn; + } + + public static void SetColumnizer(ILogLineColumnizer columnizer, BufferedDataGridView gridView) + { + var rowCount = gridView.RowCount; + var currLine = gridView.CurrentCellAddress.Y; + var currFirstLine = gridView.FirstDisplayedScrollingRowIndex; + + try { - DataGridViewTextBoxColumn lineNumberColumn = new(); - lineNumberColumn.HeaderText = "Line"; - lineNumberColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.NotSet; - lineNumberColumn.Resizable = DataGridViewTriState.NotSet; - lineNumberColumn.DividerWidth = 1; - lineNumberColumn.ReadOnly = true; - lineNumberColumn.SortMode = DataGridViewColumnSortMode.NotSortable; - - return lineNumberColumn; + gridView.Columns.Clear(); } - - public static DataGridViewColumn CreateTitleColumn(string colName) + catch (ArgumentOutOfRangeException ae) { - DataGridViewColumn titleColumn = new LogTextColumn(); - titleColumn.HeaderText = colName; - titleColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.NotSet; - titleColumn.Resizable = DataGridViewTriState.NotSet; - titleColumn.DividerWidth = 1; - titleColumn.SortMode = DataGridViewColumnSortMode.NotSortable; - - return titleColumn; + // Occures sometimes on empty gridViews (no lines) if bookmark window was closed and re-opened in floating mode. + // Don't know why. + _logger.Error(ae); } - public static void SetColumnizer(ILogLineColumnizer columnizer, BufferedDataGridView gridView) - { - int rowCount = gridView.RowCount; - int currLine = gridView.CurrentCellAddress.Y; - int currFirstLine = gridView.FirstDisplayedScrollingRowIndex; + gridView.Columns.Add(CreateMarkerColumn()); - try - { - gridView.Columns.Clear(); - } - catch (ArgumentOutOfRangeException ae) - { - // Occures sometimes on empty gridViews (no lines) if bookmark window was closed and re-opened in floating mode. - // Don't know why. - _logger.Error(ae); - } + gridView.Columns.Add(CreateLineNumberColumn()); - gridView.Columns.Add(CreateMarkerColumn()); + foreach (var colName in columnizer.GetColumnNames()) + { + gridView.Columns.Add(CreateTitleColumn(colName)); + } - gridView.Columns.Add(CreateLineNumberColumn()); + gridView.RowCount = rowCount; + if (currLine != -1) + { + gridView.CurrentCell = gridView.Rows[currLine].Cells[0]; + } + if (currFirstLine != -1) + { + gridView.FirstDisplayedScrollingRowIndex = currFirstLine; + } + //gridView.Refresh(); + //AutoResizeColumns(gridView); + } - foreach (string colName in columnizer.GetColumnNames()) + //TODO: Original name is AutoResizeColumn. Where is this used? + //TODO: Rename ConfigManager to configManager + private static void AutoResizeColumns(BufferedDataGridView gridView, IConfigManager CnofigManager) + { + try + { + gridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); + if (gridView.Columns.Count > 1 && Preferences.setLastColumnWidth && + gridView.Columns[gridView.Columns.Count - 1].Width < Preferences.lastColumnWidth + ) { - gridView.Columns.Add(CreateTitleColumn(colName)); + // It seems that using 'MinimumWidth' instead of 'Width' prevents the DataGridView's NullReferenceExceptions + //gridView.Columns[gridView.Columns.Count - 1].Width = this.Preferences.lastColumnWidth; + gridView.Columns[gridView.Columns.Count - 1].MinimumWidth = Preferences.lastColumnWidth; } + } + catch (NullReferenceException e) + { + // See https://connect.microsoft.com/VisualStudio/feedback/details/366943/autoresizecolumns-in-datagridview-throws-nullreferenceexception + // possible solution => https://stackoverflow.com/questions/36287553/nullreferenceexception-when-trying-to-set-datagridview-column-width-brings-th + // There are some rare situations with null ref exceptions when resizing columns and on filter finished + // So catch them here. Better than crashing. + _logger.Error(e, "Error while resizing columns: "); + } + } - gridView.RowCount = rowCount; - if (currLine != -1) - { - gridView.CurrentCell = gridView.Rows[currLine].Cells[0]; - } - if (currFirstLine != -1) - { - gridView.FirstDisplayedScrollingRowIndex = currFirstLine; - } - //gridView.Refresh(); - //AutoResizeColumns(gridView); + public static void ApplyDataGridViewPrefs(BufferedDataGridView dataGridView, Preferences prefs, IConfigManager configManager) + { + //TODO: This is a very bad solution and should be solved ASAP + if (ConfigManager == null) { + ConfigManager = configManager; } - //TODO: Original name is AutoResizeColumn. Where is this used? - //TODO: Rename ConfigManager to configManager - private static void AutoResizeColumns(BufferedDataGridView gridView, IConfigManager CnofigManager) + if (dataGridView.Columns.Count > 1) { - try + if (prefs.setLastColumnWidth) { - gridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells); - if (gridView.Columns.Count > 1 && Preferences.setLastColumnWidth && - gridView.Columns[gridView.Columns.Count - 1].Width < Preferences.lastColumnWidth - ) - { - // It seems that using 'MinimumWidth' instead of 'Width' prevents the DataGridView's NullReferenceExceptions - //gridView.Columns[gridView.Columns.Count - 1].Width = this.Preferences.lastColumnWidth; - gridView.Columns[gridView.Columns.Count - 1].MinimumWidth = Preferences.lastColumnWidth; - } + dataGridView.Columns[dataGridView.Columns.Count - 1].MinimumWidth = prefs.lastColumnWidth; } - catch (NullReferenceException e) + else { - // See https://connect.microsoft.com/VisualStudio/feedback/details/366943/autoresizecolumns-in-datagridview-throws-nullreferenceexception - // possible solution => https://stackoverflow.com/questions/36287553/nullreferenceexception-when-trying-to-set-datagridview-column-width-brings-th - // There are some rare situations with null ref exceptions when resizing columns and on filter finished - // So catch them here. Better than crashing. - _logger.Error(e, "Error while resizing columns: "); + // Workaround for a .NET bug which brings the DataGridView into an unstable state (causing lots of NullReferenceExceptions). + dataGridView.FirstDisplayedScrollingColumnIndex = 0; + + dataGridView.Columns[dataGridView.Columns.Count - 1].MinimumWidth = 5; // default } } - - public static void ApplyDataGridViewPrefs(BufferedDataGridView dataGridView, Preferences prefs, IConfigManager configManager) + if (dataGridView.RowCount > 0) { - //TODO: This is a very bad solution and should be solved ASAP - if (ConfigManager == null) { - ConfigManager = configManager; - } + dataGridView.UpdateRowHeightInfo(0, true); + } + dataGridView.Invalidate(); + dataGridView.Refresh(); + AutoResizeColumns(dataGridView, ConfigManager); + } - if (dataGridView.Columns.Count > 1) - { - if (prefs.setLastColumnWidth) - { - dataGridView.Columns[dataGridView.Columns.Count - 1].MinimumWidth = prefs.lastColumnWidth; - } - else - { - // Workaround for a .NET bug which brings the DataGridView into an unstable state (causing lots of NullReferenceExceptions). - dataGridView.FirstDisplayedScrollingColumnIndex = 0; + public static Rectangle BorderWidths(DataGridViewAdvancedBorderStyle advancedBorderStyle) + { + Rectangle rect = new(); - dataGridView.Columns[dataGridView.Columns.Count - 1].MinimumWidth = 5; // default - } - } - if (dataGridView.RowCount > 0) - { - dataGridView.UpdateRowHeightInfo(0, true); - } - dataGridView.Invalidate(); - dataGridView.Refresh(); - AutoResizeColumns(dataGridView, ConfigManager); + rect.X = advancedBorderStyle.Left == DataGridViewAdvancedCellBorderStyle.None ? 0 : 1; + if (advancedBorderStyle.Left == DataGridViewAdvancedCellBorderStyle.OutsetDouble || + advancedBorderStyle.Left == DataGridViewAdvancedCellBorderStyle.InsetDouble) + { + rect.X++; } - public static Rectangle BorderWidths(DataGridViewAdvancedBorderStyle advancedBorderStyle) + rect.Y = advancedBorderStyle.Top == DataGridViewAdvancedCellBorderStyle.None ? 0 : 1; + if (advancedBorderStyle.Top == DataGridViewAdvancedCellBorderStyle.OutsetDouble || + advancedBorderStyle.Top == DataGridViewAdvancedCellBorderStyle.InsetDouble) { - Rectangle rect = new(); + rect.Y++; + } - rect.X = advancedBorderStyle.Left == DataGridViewAdvancedCellBorderStyle.None ? 0 : 1; - if (advancedBorderStyle.Left == DataGridViewAdvancedCellBorderStyle.OutsetDouble || - advancedBorderStyle.Left == DataGridViewAdvancedCellBorderStyle.InsetDouble) - { - rect.X++; - } + rect.Width = advancedBorderStyle.Right == DataGridViewAdvancedCellBorderStyle.None ? 0 : 1; + if (advancedBorderStyle.Right == DataGridViewAdvancedCellBorderStyle.OutsetDouble || + advancedBorderStyle.Right == DataGridViewAdvancedCellBorderStyle.InsetDouble) + { + rect.Width++; + } - rect.Y = advancedBorderStyle.Top == DataGridViewAdvancedCellBorderStyle.None ? 0 : 1; - if (advancedBorderStyle.Top == DataGridViewAdvancedCellBorderStyle.OutsetDouble || - advancedBorderStyle.Top == DataGridViewAdvancedCellBorderStyle.InsetDouble) - { - rect.Y++; - } + rect.Height = advancedBorderStyle.Bottom == DataGridViewAdvancedCellBorderStyle.None ? 0 : 1; + if (advancedBorderStyle.Bottom == DataGridViewAdvancedCellBorderStyle.OutsetDouble || + advancedBorderStyle.Bottom == DataGridViewAdvancedCellBorderStyle.InsetDouble) + { + rect.Height++; + } - rect.Width = advancedBorderStyle.Right == DataGridViewAdvancedCellBorderStyle.None ? 0 : 1; - if (advancedBorderStyle.Right == DataGridViewAdvancedCellBorderStyle.OutsetDouble || - advancedBorderStyle.Right == DataGridViewAdvancedCellBorderStyle.InsetDouble) - { - rect.Width++; - } + //rect.Width += this.owningColumn.DividerWidth; + //rect.Height += this.owningRow.DividerHeight; - rect.Height = advancedBorderStyle.Bottom == DataGridViewAdvancedCellBorderStyle.None ? 0 : 1; - if (advancedBorderStyle.Bottom == DataGridViewAdvancedCellBorderStyle.OutsetDouble || - advancedBorderStyle.Bottom == DataGridViewAdvancedCellBorderStyle.InsetDouble) - { - rect.Height++; - } + return rect; + } - //rect.Width += this.owningColumn.DividerWidth; - //rect.Height += this.owningRow.DividerHeight; + #endregion - return rect; - } + #region Private Methods - #endregion + private static void PaintCell(ILogPaintContextUI logPaintCtx, DataGridViewCellPaintingEventArgs e, BufferedDataGridView gridView, bool noBackgroundFill, HighlightEntry groundEntry) + { + PaintHighlightedCell(logPaintCtx, e, gridView, noBackgroundFill, groundEntry); + } - #region Private Methods + private static void PaintHighlightedCell(ILogPaintContextUI logPaintCtx, DataGridViewCellPaintingEventArgs e, BufferedDataGridView gridView, bool noBackgroundFill, HighlightEntry groundEntry) + { + var value = e.Value ?? string.Empty; - private static void PaintCell(ILogPaintContextUI logPaintCtx, DataGridViewCellPaintingEventArgs e, BufferedDataGridView gridView, bool noBackgroundFill, HighlightEntry groundEntry) + IList matchList = logPaintCtx.FindHighlightMatches(value as ILogLine); + // too many entries per line seem to cause problems with the GDI + while (matchList.Count > 50) { - PaintHighlightedCell(logPaintCtx, e, gridView, noBackgroundFill, groundEntry); + matchList.RemoveAt(50); } - private static void PaintHighlightedCell(ILogPaintContextUI logPaintCtx, DataGridViewCellPaintingEventArgs e, BufferedDataGridView gridView, bool noBackgroundFill, HighlightEntry groundEntry) + if (value is Column column) { - object value = e.Value ?? string.Empty; - - IList matchList = logPaintCtx.FindHighlightMatches(value as ILogLine); - // too many entries per line seem to cause problems with the GDI - while (matchList.Count > 50) + if (string.IsNullOrEmpty(column.FullValue) == false) { - matchList.RemoveAt(50); - } + HilightMatchEntry hme = new(); + hme.StartPos = 0; + hme.Length = column.FullValue.Length; - if (value is Column column) - { - if (string.IsNullOrEmpty(column.FullValue) == false) + var he = new HighlightEntry { - HilightMatchEntry hme = new(); - hme.StartPos = 0; - hme.Length = column.FullValue.Length; - - var he = new HighlightEntry - { - SearchText = column.FullValue, - ForegroundColor = groundEntry?.ForegroundColor ?? ColorMode.ForeColor, - BackgroundColor = groundEntry?.BackgroundColor ?? Color.Empty, - IsRegEx = false, - IsCaseSensitive = false, - IsLedSwitch = false, - IsStopTail = false, - IsSetBookmark = false, - IsActionEntry = false, - IsWordMatch = false - }; - - hme.HilightEntry = he; - - matchList = MergeHighlightMatchEntries(matchList, hme); - } + SearchText = column.FullValue, + ForegroundColor = groundEntry?.ForegroundColor ?? ColorMode.ForeColor, + BackgroundColor = groundEntry?.BackgroundColor ?? Color.Empty, + IsRegEx = false, + IsCaseSensitive = false, + IsLedSwitch = false, + IsStopTail = false, + IsSetBookmark = false, + IsActionEntry = false, + IsWordMatch = false + }; + + hme.HilightEntry = he; + + matchList = MergeHighlightMatchEntries(matchList, hme); } + } - int leftPad = e.CellStyle.Padding.Left; - RectangleF rect = new(e.CellBounds.Left + leftPad, e.CellBounds.Top, e.CellBounds.Width, e.CellBounds.Height); - Rectangle borderWidths = BorderWidths(e.AdvancedBorderStyle); - Rectangle valBounds = e.CellBounds; - valBounds.Offset(borderWidths.X, borderWidths.Y); - valBounds.Width -= borderWidths.Right; - valBounds.Height -= borderWidths.Bottom; - if (e.CellStyle.Padding != Padding.Empty) - { - valBounds.Offset(e.CellStyle.Padding.Left, e.CellStyle.Padding.Top); - valBounds.Width -= e.CellStyle.Padding.Horizontal; - valBounds.Height -= e.CellStyle.Padding.Vertical; - } + var leftPad = e.CellStyle.Padding.Left; + RectangleF rect = new(e.CellBounds.Left + leftPad, e.CellBounds.Top, e.CellBounds.Width, e.CellBounds.Height); + Rectangle borderWidths = BorderWidths(e.AdvancedBorderStyle); + Rectangle valBounds = e.CellBounds; + valBounds.Offset(borderWidths.X, borderWidths.Y); + valBounds.Width -= borderWidths.Right; + valBounds.Height -= borderWidths.Bottom; + if (e.CellStyle.Padding != Padding.Empty) + { + valBounds.Offset(e.CellStyle.Padding.Left, e.CellStyle.Padding.Top); + valBounds.Width -= e.CellStyle.Padding.Horizontal; + valBounds.Height -= e.CellStyle.Padding.Vertical; + } - TextFormatFlags flags = - TextFormatFlags.Left - | TextFormatFlags.SingleLine - | TextFormatFlags.NoPrefix - | TextFormatFlags.PreserveGraphicsClipping - | TextFormatFlags.NoPadding - | TextFormatFlags.VerticalCenter - | TextFormatFlags.TextBoxControl; + TextFormatFlags flags = + TextFormatFlags.Left + | TextFormatFlags.SingleLine + | TextFormatFlags.NoPrefix + | TextFormatFlags.PreserveGraphicsClipping + | TextFormatFlags.NoPadding + | TextFormatFlags.VerticalCenter + | TextFormatFlags.TextBoxControl; - // | TextFormatFlags.VerticalCenter - // | TextFormatFlags.TextBoxControl - // TextFormatFlags.SingleLine - //TextRenderer.DrawText(e.Graphics, e.Value as String, e.CellStyle.Font, valBounds, Color.FromKnownColor(KnownColor.Black), flags); + // | TextFormatFlags.VerticalCenter + // | TextFormatFlags.TextBoxControl + // TextFormatFlags.SingleLine + //TextRenderer.DrawText(e.Graphics, e.Value as String, e.CellStyle.Font, valBounds, Color.FromKnownColor(KnownColor.Black), flags); - Point wordPos = valBounds.Location; - Size proposedSize = new(valBounds.Width, valBounds.Height); + Point wordPos = valBounds.Location; + Size proposedSize = new(valBounds.Width, valBounds.Height); - Rectangle r = gridView.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true); - e.Graphics.SetClip(e.CellBounds); + Rectangle r = gridView.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true); + e.Graphics.SetClip(e.CellBounds); - foreach (HilightMatchEntry matchEntry in matchList) - { - Font font = matchEntry != null && matchEntry.HilightEntry.IsBold - ? logPaintCtx.BoldFont - : logPaintCtx.NormalFont; + foreach (HilightMatchEntry matchEntry in matchList) + { + Font font = matchEntry != null && matchEntry.HilightEntry.IsBold + ? logPaintCtx.BoldFont + : logPaintCtx.NormalFont; - Brush bgBrush = matchEntry.HilightEntry.BackgroundColor != Color.Empty - ? new SolidBrush(matchEntry.HilightEntry.BackgroundColor) - : null; + Brush bgBrush = matchEntry.HilightEntry.BackgroundColor != Color.Empty + ? new SolidBrush(matchEntry.HilightEntry.BackgroundColor) + : null; - string matchWord = string.Empty; - if (value is Column again) + var matchWord = string.Empty; + if (value is Column again) + { + if (string.IsNullOrEmpty(again.FullValue) == false) { - if (string.IsNullOrEmpty(again.FullValue) == false) - { - matchWord = again.FullValue.Substring(matchEntry.StartPos, matchEntry.Length); - } + matchWord = again.FullValue.Substring(matchEntry.StartPos, matchEntry.Length); } + } - Size wordSize = TextRenderer.MeasureText(e.Graphics, matchWord, font, proposedSize, flags); - wordSize.Height = e.CellBounds.Height; - Rectangle wordRect = new(wordPos, wordSize); + Size wordSize = TextRenderer.MeasureText(e.Graphics, matchWord, font, proposedSize, flags); + wordSize.Height = e.CellBounds.Height; + Rectangle wordRect = new(wordPos, wordSize); - Color foreColor = matchEntry.HilightEntry.ForegroundColor; - if ((e.State & DataGridViewElementStates.Selected) != DataGridViewElementStates.Selected) + Color foreColor = matchEntry.HilightEntry.ForegroundColor; + if ((e.State & DataGridViewElementStates.Selected) != DataGridViewElementStates.Selected) + { + if (!noBackgroundFill && bgBrush != null && !matchEntry.HilightEntry.NoBackground) { - if (!noBackgroundFill && bgBrush != null && !matchEntry.HilightEntry.NoBackground) - { - e.Graphics.FillRectangle(bgBrush, wordRect); - } + e.Graphics.FillRectangle(bgBrush, wordRect); } - else + } + else + { + if (foreColor.Equals(Color.Black)) { - if (foreColor.Equals(Color.Black)) - { - foreColor = Color.White; - } + foreColor = Color.White; } - TextRenderer.DrawText(e.Graphics, matchWord, font, wordRect, foreColor, flags); - - wordPos.Offset(wordSize.Width, 0); - bgBrush?.Dispose(); } + TextRenderer.DrawText(e.Graphics, matchWord, font, wordRect, foreColor, flags); + + wordPos.Offset(wordSize.Width, 0); + bgBrush?.Dispose(); } + } - /// - /// Builds a list of HilightMatchEntry objects. A HilightMatchEntry spans over a region that is painted with the same foreground and - /// background colors. - /// All regions which don't match a word-mode entry will be painted with the colors of a default entry (groundEntry). This is either the - /// first matching non-word-mode highlight entry or a black-on-white default (if no matching entry was found). - /// - /// List of all highlight matches for the current cell - /// The entry that is used as the default. - /// List of HilightMatchEntry objects. The list spans over the whole cell and contains color infos for every substring. - private static IList MergeHighlightMatchEntries(IList matchList, HilightMatchEntry groundEntry) + /// + /// Builds a list of HilightMatchEntry objects. A HilightMatchEntry spans over a region that is painted with the same foreground and + /// background colors. + /// All regions which don't match a word-mode entry will be painted with the colors of a default entry (groundEntry). This is either the + /// first matching non-word-mode highlight entry or a black-on-white default (if no matching entry was found). + /// + /// List of all highlight matches for the current cell + /// The entry that is used as the default. + /// List of HilightMatchEntry objects. The list spans over the whole cell and contains color infos for every substring. + private static IList MergeHighlightMatchEntries(IList matchList, HilightMatchEntry groundEntry) + { + // Fill an area with lenth of whole text with a default hilight entry + var entryArray = new HighlightEntry[groundEntry.Length]; + for (var i = 0; i < entryArray.Length; ++i) { - // Fill an area with lenth of whole text with a default hilight entry - HighlightEntry[] entryArray = new HighlightEntry[groundEntry.Length]; - for (int i = 0; i < entryArray.Length; ++i) - { - entryArray[i] = groundEntry.HilightEntry; - } + entryArray[i] = groundEntry.HilightEntry; + } - // "overpaint" with all matching word match enries - // Non-word-mode matches will not overpaint because they use the groundEntry - foreach (HilightMatchEntry me in matchList) + // "overpaint" with all matching word match enries + // Non-word-mode matches will not overpaint because they use the groundEntry + foreach (HilightMatchEntry me in matchList) + { + var endPos = me.StartPos + me.Length; + for (var i = me.StartPos; i < endPos; ++i) { - int endPos = me.StartPos + me.Length; - for (int i = me.StartPos; i < endPos; ++i) + if (me.HilightEntry.IsWordMatch) { - if (me.HilightEntry.IsWordMatch) - { - entryArray[i] = me.HilightEntry; - } - //else - //{ - // //entryArray[i].ForegroundColor = me.HilightEntry.ForegroundColor; - //} + entryArray[i] = me.HilightEntry; } + //else + //{ + // //entryArray[i].ForegroundColor = me.HilightEntry.ForegroundColor; + //} } + } - // collect areas with same hilight entry and build new highlight match entries for it - IList mergedList = new List(); - if (entryArray.Length > 0) + // collect areas with same hilight entry and build new highlight match entries for it + IList mergedList = new List(); + if (entryArray.Length > 0) + { + HighlightEntry currentEntry = entryArray[0]; + var lastStartPos = 0; + var pos = 0; + for (; pos < entryArray.Length; ++pos) { - HighlightEntry currentEntry = entryArray[0]; - int lastStartPos = 0; - int pos = 0; - for (; pos < entryArray.Length; ++pos) + if (entryArray[pos] != currentEntry) { - if (entryArray[pos] != currentEntry) - { - HilightMatchEntry me = new(); - me.StartPos = lastStartPos; - me.Length = pos - lastStartPos; - me.HilightEntry = currentEntry; - mergedList.Add(me); - currentEntry = entryArray[pos]; - lastStartPos = pos; - } + HilightMatchEntry me = new(); + me.StartPos = lastStartPos; + me.Length = pos - lastStartPos; + me.HilightEntry = currentEntry; + mergedList.Add(me); + currentEntry = entryArray[pos]; + lastStartPos = pos; } - HilightMatchEntry me2 = new(); - me2.StartPos = lastStartPos; - me2.Length = pos - lastStartPos; - me2.HilightEntry = currentEntry; - mergedList.Add(me2); } - return mergedList; + HilightMatchEntry me2 = new(); + me2.StartPos = lastStartPos; + me2.Length = pos - lastStartPos; + me2.HilightEntry = currentEntry; + mergedList.Add(me2); } - - #endregion + return mergedList; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert.UI/Extensions/Forms/LineToolStripSeparatorExtension.cs b/src/LogExpert.UI/Extensions/Forms/LineToolStripSeparatorExtension.cs index f63b4bb1..4c30c9a4 100644 --- a/src/LogExpert.UI/Extensions/Forms/LineToolStripSeparatorExtension.cs +++ b/src/LogExpert.UI/Extensions/Forms/LineToolStripSeparatorExtension.cs @@ -15,9 +15,9 @@ public LineToolStripSeparatorExtension() private void OnExtendedToolStripSeparatorPaint(object sender, PaintEventArgs e) { // Get the separator's width and height. - ToolStripSeparator toolStripSeparator = (ToolStripSeparator)sender; - int width = toolStripSeparator.Width; - int height = toolStripSeparator.Height; + var toolStripSeparator = (ToolStripSeparator)sender; + var width = toolStripSeparator.Width; + var height = toolStripSeparator.Height; // Choose the colors for drawing. // I've used Color.White as the foreColor. diff --git a/src/LogExpert.UI/Extensions/Forms/MenuToolStripSeparatorExtension.cs b/src/LogExpert.UI/Extensions/Forms/MenuToolStripSeparatorExtension.cs index b2dc6af7..82e44e39 100644 --- a/src/LogExpert.UI/Extensions/Forms/MenuToolStripSeparatorExtension.cs +++ b/src/LogExpert.UI/Extensions/Forms/MenuToolStripSeparatorExtension.cs @@ -20,9 +20,9 @@ private void OnExtendedToolStripSeparatorPaint(object? sender, PaintEventArgs e) } // Get the separator's width and height. - ToolStripSeparator toolStripSeparator = sender as ToolStripSeparator; - int width = toolStripSeparator.Width; - int height = toolStripSeparator.Height; + var toolStripSeparator = sender as ToolStripSeparator; + var width = toolStripSeparator.Width; + var height = toolStripSeparator.Height; // Choose the colors for drawing. // I've used Color.White as the foreColor. diff --git a/src/LogExpert.UI/Extensions/Utils.cs b/src/LogExpert.UI/Extensions/Utils.cs index f753a1fd..6b2c2d67 100644 --- a/src/LogExpert.UI/Extensions/Utils.cs +++ b/src/LogExpert.UI/Extensions/Utils.cs @@ -1,57 +1,56 @@ -namespace LogExpert.UI.Extensions +namespace LogExpert.UI.Extensions; + +internal static class Utils { - internal static class Utils + public static string GetWordFromPos(int xPos, string text, Graphics g, Font font) { - public static string GetWordFromPos(int xPos, string text, Graphics g, Font font) - { - string[] words = text.Split([' ', '.', ':', ';']); + var words = text.Split([' ', '.', ':', ';']); - int index = 0; + var index = 0; - List crList = []; + List crList = []; - for (int i = 0; i < words.Length; ++i) - { - crList.Add(new CharacterRange(index, words[i].Length)); - index += words[i].Length; - } + for (var i = 0; i < words.Length; ++i) + { + crList.Add(new CharacterRange(index, words[i].Length)); + index += words[i].Length; + } - CharacterRange[] crArray = [.. crList]; + CharacterRange[] crArray = [.. crList]; - StringFormat stringFormat = new(StringFormat.GenericTypographic) - { - Trimming = StringTrimming.None, - FormatFlags = StringFormatFlags.NoClip - }; + StringFormat stringFormat = new(StringFormat.GenericTypographic) + { + Trimming = StringTrimming.None, + FormatFlags = StringFormatFlags.NoClip + }; - stringFormat.SetMeasurableCharacterRanges(crArray); + stringFormat.SetMeasurableCharacterRanges(crArray); - RectangleF rect = new(0, 0, 3000, 20); - Region[] stringRegions = g.MeasureCharacterRanges(text, font, rect, stringFormat); + RectangleF rect = new(0, 0, 3000, 20); + Region[] stringRegions = g.MeasureCharacterRanges(text, font, rect, stringFormat); - bool found = false; + var found = false; - int y = 0; + var y = 0; - foreach (Region regio in stringRegions) + foreach (Region regio in stringRegions) + { + if (regio.IsVisible(xPos, 3, g)) { - if (regio.IsVisible(xPos, 3, g)) - { - found = true; - break; - } - - y++; + found = true; + break; } - if (found) - { - return words[y]; - } - else - { - return null; - } + y++; + } + + if (found) + { + return words[y]; + } + else + { + return null; } } } diff --git a/src/LogExpert.UI/Extensions/Win32.cs b/src/LogExpert.UI/Extensions/Win32.cs index b0f9e92e..a039e711 100644 --- a/src/LogExpert.UI/Extensions/Win32.cs +++ b/src/LogExpert.UI/Extensions/Win32.cs @@ -2,150 +2,149 @@ using System.Runtime.InteropServices; using System.Runtime.Versioning; -namespace LogExpert.UI.Extensions +namespace LogExpert.UI.Extensions; + +[SupportedOSPlatform("windows")] +internal static partial class Win32 //NativeMethods { - [SupportedOSPlatform("windows")] - internal static partial class Win32 //NativeMethods + #region Fields + + public const long SM_CYVSCROLL = 20; + public const long SM_CXHSCROLL = 21; + public const long SM_CXVSCROLL = 2; + public const long SM_CYHSCROLL = 3; + private const int DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19; + private const int DWMWA_USE_IMMERSIVE_DARK_MODE = 20; + + #endregion + + #region Library Imports + [LibraryImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool DestroyIcon(nint hIcon); + + [LibraryImport("User32.dll")] + public static partial int SetForegroundWindow(nint hWnd); + + [LibraryImport("user32.dll")] + public static partial long GetSystemMetricsForDpi(long index); + + [LibraryImport("user32.dll")] + public static partial long GetSystemMetrics(long index); + + [LibraryImport("user32.dll")] + public static partial short GetKeyState(int vKey); + + /* + UINT ExtractIconEx( + LPCTSTR lpszFile, + int nIconIndex, + HICON *phiconLarge, + HICON *phiconSmall, + UINT nIcons + ); + * */ + [LibraryImport("shell32.dll", StringMarshalling = StringMarshalling.Utf16)] + public static partial uint ExtractIconEx( + string fileName, + int iconIndex, + ref nint iconsLarge, + ref nint iconsSmall, + uint numIcons + ); + + #region TitleBarDarkMode + [LibraryImport("dwmapi.dll")] + public static partial int DwmSetWindowAttribute(nint hwnd, int attr, ref int attrValue, int attrSize); + #endregion + #endregion + + #region Public methods + + public static Icon LoadIconFromExe(string fileName, int index) + { + //IntPtr[] smallIcons = new IntPtr[1]; + //IntPtr[] largeIcons = new IntPtr[1]; + nint smallIcons = new(); + nint largeIcons = new(); + var num = (int)ExtractIconEx(fileName, index, ref largeIcons, ref smallIcons, 1); + if (num > 0 && smallIcons != nint.Zero) + { + var icon = (Icon)Icon.FromHandle(smallIcons).Clone(); + DestroyIcon(smallIcons); + return icon; + } + if (num > 0 && largeIcons != nint.Zero) + { + var icon = (Icon)Icon.FromHandle(largeIcons).Clone(); + DestroyIcon(largeIcons); + return icon; + } + return null; + } + + public static Icon[,] ExtractIcons(string fileName) { - #region Fields - - public const long SM_CYVSCROLL = 20; - public const long SM_CXHSCROLL = 21; - public const long SM_CXVSCROLL = 2; - public const long SM_CYHSCROLL = 3; - private const int DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19; - private const int DWMWA_USE_IMMERSIVE_DARK_MODE = 20; - - #endregion - - #region Library Imports - [LibraryImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - public static partial bool DestroyIcon(nint hIcon); - - [LibraryImport("User32.dll")] - public static partial int SetForegroundWindow(nint hWnd); - - [LibraryImport("user32.dll")] - public static partial long GetSystemMetricsForDpi(long index); - - [LibraryImport("user32.dll")] - public static partial long GetSystemMetrics(long index); - - [LibraryImport("user32.dll")] - public static partial short GetKeyState(int vKey); - - /* - UINT ExtractIconEx( - LPCTSTR lpszFile, - int nIconIndex, - HICON *phiconLarge, - HICON *phiconSmall, - UINT nIcons - ); - * */ - [LibraryImport("shell32.dll", StringMarshalling = StringMarshalling.Utf16)] - public static partial uint ExtractIconEx( - string fileName, - int iconIndex, - ref nint iconsLarge, - ref nint iconsSmall, - uint numIcons - ); - - #region TitleBarDarkMode - [LibraryImport("dwmapi.dll")] - public static partial int DwmSetWindowAttribute(nint hwnd, int attr, ref int attrValue, int attrSize); - #endregion - #endregion - - #region Public methods - - public static Icon LoadIconFromExe(string fileName, int index) + var smallIcon = nint.Zero; + var largeIcon = nint.Zero; + var iconCount = (int)ExtractIconEx(fileName, -1, ref largeIcon, ref smallIcon, 0); + if (iconCount <= 0) { - //IntPtr[] smallIcons = new IntPtr[1]; - //IntPtr[] largeIcons = new IntPtr[1]; - nint smallIcons = new(); - nint largeIcons = new(); - int num = (int)ExtractIconEx(fileName, index, ref largeIcons, ref smallIcons, 1); - if (num > 0 && smallIcons != nint.Zero) + return null; + } + + nint smallIcons = new(); + nint largeIcons = new(); + var result = new Icon[2, iconCount]; + + for (var i = 0; i < iconCount; ++i) + { + var num = (int)ExtractIconEx(fileName, i, ref largeIcons, ref smallIcons, 1); + if (smallIcons != nint.Zero) { - Icon icon = (Icon)Icon.FromHandle(smallIcons).Clone(); + result[0, i] = (Icon)Icon.FromHandle(smallIcons).Clone(); DestroyIcon(smallIcons); - return icon; } - if (num > 0 && largeIcons != nint.Zero) + else { - Icon icon = (Icon)Icon.FromHandle(largeIcons).Clone(); - DestroyIcon(largeIcons); - return icon; + result[0, i] = null; } - return null; - } - - public static Icon[,] ExtractIcons(string fileName) - { - nint smallIcon = nint.Zero; - nint largeIcon = nint.Zero; - int iconCount = (int)ExtractIconEx(fileName, -1, ref largeIcon, ref smallIcon, 0); - if (iconCount <= 0) + if (num > 0 && largeIcons != nint.Zero) { - return null; + result[1, i] = (Icon)Icon.FromHandle(largeIcons).Clone(); + DestroyIcon(largeIcons); } - - nint smallIcons = new(); - nint largeIcons = new(); - Icon[,] result = new Icon[2, iconCount]; - - for (int i = 0; i < iconCount; ++i) + else { - int num = (int)ExtractIconEx(fileName, i, ref largeIcons, ref smallIcons, 1); - if (smallIcons != nint.Zero) - { - result[0, i] = (Icon)Icon.FromHandle(smallIcons).Clone(); - DestroyIcon(smallIcons); - } - else - { - result[0, i] = null; - } - if (num > 0 && largeIcons != nint.Zero) - { - result[1, i] = (Icon)Icon.FromHandle(largeIcons).Clone(); - DestroyIcon(largeIcons); - } - else - { - result[1, i] = null; - } + result[1, i] = null; } - return result; } + return result; + } - #endregion - - #region Private Methods - - public static bool UseImmersiveDarkMode(nint handle, bool enabled) - { - - var attribute = DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1; - if (IsWindows10OrGreater(18985)) - { - attribute = DWMWA_USE_IMMERSIVE_DARK_MODE; - } + #endregion - int useImmersiveDarkMode = enabled ? 1 : 0; - return DwmSetWindowAttribute(handle, attribute, ref useImmersiveDarkMode, sizeof(int)) == 0; + #region Private Methods - } + public static bool UseImmersiveDarkMode(nint handle, bool enabled) + { - private static bool IsWindows10OrGreater(int build = -1) + var attribute = DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1; + if (IsWindows10OrGreater(18985)) { - return Environment.OSVersion.Version.Major >= 10 && Environment.OSVersion.Version.Build >= build; + attribute = DWMWA_USE_IMMERSIVE_DARK_MODE; } - #endregion TitleBarDarkMode + var useImmersiveDarkMode = enabled ? 1 : 0; + return DwmSetWindowAttribute(handle, attribute, ref useImmersiveDarkMode, sizeof(int)) == 0; } + + private static bool IsWindows10OrGreater(int build = -1) + { + return Environment.OSVersion.Version.Major >= 10 && Environment.OSVersion.Version.Build >= build; + } + + #endregion TitleBarDarkMode + } \ No newline at end of file diff --git a/src/LogExpert.UI/Interface/ILogPaintContextUI.cs b/src/LogExpert.UI/Interface/ILogPaintContextUI.cs index dcd8ae41..39557972 100644 --- a/src/LogExpert.UI/Interface/ILogPaintContextUI.cs +++ b/src/LogExpert.UI/Interface/ILogPaintContextUI.cs @@ -2,34 +2,33 @@ using LogExpert.Core.Entities; using LogExpert.Core.Interface; -namespace LogExpert.UI.Interface +namespace LogExpert.UI.Interface; + +/// +/// Declares methods that are needed for drawing log lines. Used by PaintHelper. +/// +public interface ILogPaintContextUI : ILogPaintContext { - /// - /// Declares methods that are needed for drawing log lines. Used by PaintHelper. - /// - public interface ILogPaintContextUI : ILogPaintContext - { - #region Properties + #region Properties - Font MonospacedFont { get; } // Font font = new Font("Courier New", this.Preferences.fontSize, FontStyle.Bold); - Font NormalFont { get; } - Font BoldFont { get; } - Color BookmarkColor { get; } + Font MonospacedFont { get; } // Font font = new Font("Courier New", this.Preferences.fontSize, FontStyle.Bold); + Font NormalFont { get; } + Font BoldFont { get; } + Color BookmarkColor { get; } - #endregion + #endregion - #region Public methods + #region Public methods - ILogLine GetLogLine(int lineNum); + ILogLine GetLogLine(int lineNum); - IColumn GetCellValue(int rowIndex, int columnIndex); + IColumn GetCellValue(int rowIndex, int columnIndex); - Bookmark GetBookmarkForLine(int lineNum); + Bookmark GetBookmarkForLine(int lineNum); - HighlightEntry FindHighlightEntry(ITextValue line, bool noWordMatches); + HighlightEntry FindHighlightEntry(ITextValue line, bool noWordMatches); - IList FindHighlightMatches(ITextValue line); + IList FindHighlightMatches(ITextValue line); - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/LogExpert/Classes/CommandLine/CmdLine.cs b/src/LogExpert/Classes/CommandLine/CmdLine.cs index 19ad74d0..07155cb5 100644 --- a/src/LogExpert/Classes/CommandLine/CmdLine.cs +++ b/src/LogExpert/Classes/CommandLine/CmdLine.cs @@ -5,185 +5,184 @@ //TODO: Replace with https://github.com/commandlineparser/commandline //TODO: or with this https://github.com/natemcmaster/CommandLineUtils -namespace LogExpert.Classes.CommandLine +namespace LogExpert.Classes.CommandLine; + +/// +/// Represents an string command line parameter. +/// +public class CmdLineString(string name, bool required, string helpMessage) : CmdLineParameter(name, required, helpMessage) { - /// - /// Represents an string command line parameter. - /// - public class CmdLineString(string name, bool required, string helpMessage) : CmdLineParameter(name, required, helpMessage) - { - #region Public methods + #region Public methods - public static implicit operator string(CmdLineString s) - { - return s.Value; - } - - #endregion + public static implicit operator string(CmdLineString s) + { + return s.Value; } - /// - /// Provides a simple strongly typed interface to work with command line parameters. - /// - public class CmdLine - { - #region Fields + #endregion +} - // A private dictonary containing the parameters. - private readonly Dictionary parameters = []; +/// +/// Provides a simple strongly typed interface to work with command line parameters. +/// +public class CmdLine +{ + #region Fields - #endregion + // A private dictonary containing the parameters. + private readonly Dictionary parameters = []; - #region cTor + #endregion - /// - /// Creats a new empty command line object. - /// - public CmdLine() - { - } + #region cTor + + /// + /// Creats a new empty command line object. + /// + public CmdLine() + { + } - #endregion + #endregion - #region Properties + #region Properties - /// - /// Returns a command line parameter by the name. - /// - /// The name of the parameter (the word after the initial hyphen (-). - /// A reference to the named comman line object. - public CmdLineParameter this[string name] + /// + /// Returns a command line parameter by the name. + /// + /// The name of the parameter (the word after the initial hyphen (-). + /// A reference to the named comman line object. + public CmdLineParameter this[string name] + { + get { - get + if (parameters.TryGetValue(name, out CmdLineParameter value) == false) { - if (parameters.TryGetValue(name, out CmdLineParameter value) == false) - { - throw new CmdLineException(name, "Not a registered parameter."); - } - return value; + throw new CmdLineException(name, "Not a registered parameter."); } + return value; } + } - #endregion + #endregion - #region Public methods + #region Public methods - /// - /// Registers a parameter to be used and adds it to the help screen. - /// - /// The parameter to add. - public void RegisterParameter(CmdLineParameter parameter) + /// + /// Registers a parameter to be used and adds it to the help screen. + /// + /// The parameter to add. + public void RegisterParameter(CmdLineParameter parameter) + { + if (parameters.ContainsKey(parameter.Name)) { - if (parameters.ContainsKey(parameter.Name)) - { - throw new CmdLineException(parameter.Name, "Parameter is already registered."); - } - parameters.Add(parameter.Name, parameter); + throw new CmdLineException(parameter.Name, "Parameter is already registered."); } + parameters.Add(parameter.Name, parameter); + } - /// - /// Registers parameters to be used and adds hem to the help screen. - /// - /// The parameter to add. - public void RegisterParameter(CmdLineParameter[] parameters) + /// + /// Registers parameters to be used and adds hem to the help screen. + /// + /// The parameter to add. + public void RegisterParameter(CmdLineParameter[] parameters) + { + foreach (CmdLineParameter p in parameters) { - foreach (CmdLineParameter p in parameters) - { - RegisterParameter(p); - } + RegisterParameter(p); } + } - /// - /// Parses the command line and sets the value of each registered parmaters. - /// - /// The arguments array sent to main() - /// Any reminding strings after arguments has been processed. - public string[] Parse(string[] args) - { - int i = 0; + /// + /// Parses the command line and sets the value of each registered parmaters. + /// + /// The arguments array sent to main() + /// Any reminding strings after arguments has been processed. + public string[] Parse(string[] args) + { + var i = 0; - List new_args = []; + List new_args = []; - while (i < args.Length) + while (i < args.Length) + { + if (args[i].Length > 1 && args[i][0] == '-') { - if (args[i].Length > 1 && args[i][0] == '-') + // The current string is a parameter name + var key = args[i][1..].ToLower(); + var argsValue = string.Empty; + i++; + if (i < args.Length) { - // The current string is a parameter name - string key = args[i][1..].ToLower(); - string argsValue = string.Empty; - i++; - if (i < args.Length) + if (args[i].Length > 0 && args[i][0] == '-') { - if (args[i].Length > 0 && args[i][0] == '-') - { - // The next string is a new parameter, do not nothing - } - else - { - // The next string is a value, read the value and move forward - argsValue = args[i]; - i++; - } + // The next string is a new parameter, do not nothing } - if (parameters.TryGetValue(key, out CmdLineParameter cmdLineParameter) == false) + else { - throw new CmdLineException(key, "Parameter is not allowed."); + // The next string is a value, read the value and move forward + argsValue = args[i]; + i++; } - - if (cmdLineParameter.Exists) - { - throw new CmdLineException(key, "Parameter is specified more than once."); - } - - cmdLineParameter.SetValue(argsValue); } - else + if (parameters.TryGetValue(key, out CmdLineParameter cmdLineParameter) == false) { - new_args.Add(args[i]); - i++; + throw new CmdLineException(key, "Parameter is not allowed."); } - } - - // Check that required parameters are present in the command line. - foreach (string key in parameters.Keys) - { - if (parameters[key].Required && parameters[key].Exists == false) + if (cmdLineParameter.Exists) { - throw new CmdLineException(key, "Required parameter is not found."); + throw new CmdLineException(key, "Parameter is specified more than once."); } - } - return new_args.ToArray(); + cmdLineParameter.SetValue(argsValue); + } + else + { + new_args.Add(args[i]); + i++; + } } - /// - /// Generates the help screen. - /// - public string HelpScreen() + + // Check that required parameters are present in the command line. + foreach (var key in parameters.Keys) { - int len = 0; - foreach (string key in parameters.Keys) + if (parameters[key].Required && parameters[key].Exists == false) { - len = Math.Max(len, key.Length); + throw new CmdLineException(key, "Required parameter is not found."); } + } - string help = "\nParameters:\n\n"; - foreach (string key in parameters.Keys) + return new_args.ToArray(); + } + + /// + /// Generates the help screen. + /// + public string HelpScreen() + { + var len = 0; + foreach (var key in parameters.Keys) + { + len = Math.Max(len, key.Length); + } + + var help = "\nParameters:\n\n"; + foreach (var key in parameters.Keys) + { + var s = "-" + parameters[key].Name; + while (s.Length < len + 3) { - string s = "-" + parameters[key].Name; - while (s.Length < len + 3) - { - s += " "; - } - s += parameters[key].Help + "\n"; - help += s; + s += " "; } - return help; + s += parameters[key].Help + "\n"; + help += s; } - - #endregion + return help; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert/Classes/CommandLine/CmdLineException.cs b/src/LogExpert/Classes/CommandLine/CmdLineException.cs index a89bc570..01e67c7d 100644 --- a/src/LogExpert/Classes/CommandLine/CmdLineException.cs +++ b/src/LogExpert/Classes/CommandLine/CmdLineException.cs @@ -5,27 +5,30 @@ //TODO: Replace with https://github.com/commandlineparser/commandline //TODO: or with this https://github.com/natemcmaster/CommandLineUtils -namespace LogExpert.Classes.CommandLine +namespace LogExpert.Classes.CommandLine; + +/// +/// Represents an error occuring during command line parsing. +/// +public class CmdLineException : Exception { - /// - /// Represents an error occuring during command line parsing. - /// - public class CmdLineException : Exception + #region cTor + + public CmdLineException (string parameter, string message) : base($"Syntax error of parameter -{parameter}: {message}") { - #region cTor + } - public CmdLineException(string parameter, string message) - : - base(string.Format("Syntax error of parameter -{0}: {1}", parameter, message)) - { - } + public CmdLineException (string message) : base(message) + { + } - public CmdLineException(string message) - : - base(message) - { - } + public CmdLineException () + { + } - #endregion + public CmdLineException (string message, Exception innerException) : base(message, innerException) + { } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert/Classes/CommandLine/CmdLineInt.cs b/src/LogExpert/Classes/CommandLine/CmdLineInt.cs index de6394b8..c67dd9ad 100644 --- a/src/LogExpert/Classes/CommandLine/CmdLineInt.cs +++ b/src/LogExpert/Classes/CommandLine/CmdLineInt.cs @@ -5,98 +5,97 @@ //TODO: Replace with https://github.com/commandlineparser/commandline //TODO: or with this https://github.com/natemcmaster/CommandLineUtils -namespace LogExpert.Classes.CommandLine +namespace LogExpert.Classes.CommandLine; + +/// +/// Represents an integer command line parameter. +/// +public class CmdLineInt : CmdLineParameter { - /// - /// Represents an integer command line parameter. - /// - public class CmdLineInt : CmdLineParameter - { - #region Fields + #region Fields - private readonly int _max = int.MaxValue; - private readonly int _min = int.MinValue; + private readonly int _max = int.MaxValue; + private readonly int _min = int.MinValue; - #endregion + #endregion - #region cTor + #region cTor - /// - /// Creates a new instance of this class. - /// - /// Name of parameter. - /// Require that the parameter is present in the command line. - /// The explanation of the parameter to add to the help screen. - public CmdLineInt(string name, bool required, string helpMessage) - : base(name, required, helpMessage) - { - } + /// + /// Creates a new instance of this class. + /// + /// Name of parameter. + /// Require that the parameter is present in the command line. + /// The explanation of the parameter to add to the help screen. + public CmdLineInt(string name, bool required, string helpMessage) + : base(name, required, helpMessage) + { + } - /// - /// Creates a new instance of this class. - /// - /// Name of parameter. - /// Require that the parameter is present in the command line. - /// The explanation of the parameter to add to the help screen. - /// The minimum value of the parameter. - /// The maximum valie of the parameter. - public CmdLineInt(string name, bool required, string helpMessage, int min, int max) - : base(name, required, helpMessage) - { - _min = min; - _max = max; - } + /// + /// Creates a new instance of this class. + /// + /// Name of parameter. + /// Require that the parameter is present in the command line. + /// The explanation of the parameter to add to the help screen. + /// The minimum value of the parameter. + /// The maximum valie of the parameter. + public CmdLineInt(string name, bool required, string helpMessage, int min, int max) + : base(name, required, helpMessage) + { + _min = min; + _max = max; + } - #endregion + #endregion - #region Properties + #region Properties - /// - /// Returns the current value of the parameter. - /// - new public int Value { get; private set; } + /// + /// Returns the current value of the parameter. + /// + new public int Value { get; private set; } - #endregion + #endregion - #region Public methods + #region Public methods - /// - /// Sets the value of the parameter. - /// - /// A string containing a integer expression. - public override void SetValue(string value) + /// + /// Sets the value of the parameter. + /// + /// A string containing a integer expression. + public override void SetValue(string value) + { + base.SetValue(value); + int i; + try { - base.SetValue(value); - int i = 0; - try - { - i = Convert.ToInt32(value); - } - catch (Exception) - { - throw new CmdLineException(Name, "Value is not an integer."); - } - if (i < _min) - { - throw new CmdLineException(Name, string.Format("Value must be greather or equal to {0}.", _min)); - } - if (i > _max) - { - throw new CmdLineException(Name, string.Format("Value must be less or equal to {0}.", _max)); - } - Value = i; + i = Convert.ToInt32(value); } - - /// - /// A implicit converion to a int data type. - /// - /// - /// - public static implicit operator int(CmdLineInt s) + catch (Exception) + { + throw new CmdLineException(Name, "Value is not an integer."); + } + if (i < _min) { - return s.Value; + throw new CmdLineException(Name, string.Format("Value must be greather or equal to {0}.", _min)); } + if (i > _max) + { + throw new CmdLineException(Name, string.Format("Value must be less or equal to {0}.", _max)); + } + Value = i; + } - #endregion + /// + /// A implicit converion to a int data type. + /// + /// + /// + public static implicit operator int(CmdLineInt s) + { + return s.Value; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert/Classes/CommandLine/CmdLineParameter.cs b/src/LogExpert/Classes/CommandLine/CmdLineParameter.cs index 9f7f9db8..5143ead3 100644 --- a/src/LogExpert/Classes/CommandLine/CmdLineParameter.cs +++ b/src/LogExpert/Classes/CommandLine/CmdLineParameter.cs @@ -5,62 +5,61 @@ //TODO: Replace with https://github.com/commandlineparser/commandline //TODO: or with this https://github.com/natemcmaster/CommandLineUtils -namespace LogExpert.Classes.CommandLine +namespace LogExpert.Classes.CommandLine; + +/// +/// Represents a command line parameter. +/// Parameters are words in the command line beginning with a hyphen (-). +/// The value of the parameter is the next word in +/// +/// +/// Creates a new instance of this class. +/// +/// Name of parameter. +/// Require that the parameter is present in the command line. +/// The explanation of the parameter to add to the help screen. +public class CmdLineParameter(string name, bool required, string helpMessage) { + #region Properties + /// - /// Represents a command line parameter. - /// Parameters are words in the command line beginning with a hyphen (-). - /// The value of the parameter is the next word in + /// Returns the value of the parameter. /// - /// - /// Creates a new instance of this class. - /// - /// Name of parameter. - /// Require that the parameter is present in the command line. - /// The explanation of the parameter to add to the help screen. - public class CmdLineParameter(string name, bool required, string helpMessage) - { - #region Properties - - /// - /// Returns the value of the parameter. - /// - public string Value { get; private set; } = ""; - - /// - /// Returns the help message associated with the parameter. - /// - public string Help { get; } = helpMessage; + public string Value { get; private set; } = ""; - /// - /// Returns true if the parameter was found in the command line. - /// - public bool Exists { get; private set; } = false; + /// + /// Returns the help message associated with the parameter. + /// + public string Help { get; } = helpMessage; - /// - /// Returns true if the parameter is required in the command line. - /// - public bool Required { get; } = required; + /// + /// Returns true if the parameter was found in the command line. + /// + public bool Exists { get; private set; } - /// - /// Returns the name of the parameter. - /// - public string Name { get; } = name; + /// + /// Returns true if the parameter is required in the command line. + /// + public bool Required { get; } = required; - #endregion + /// + /// Returns the name of the parameter. + /// + public string Name { get; } = name; - #region Public methods + #endregion - /// - /// Sets the value of the parameter. - /// - /// A string containing a integer expression. - public virtual void SetValue(string value) - { - Value = value; - Exists = true; - } + #region Public methods - #endregion + /// + /// Sets the value of the parameter. + /// + /// A string containing a integer expression. + public virtual void SetValue(string value) + { + Value = value; + Exists = true; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert/Classes/CommandLine/ConsoleCmdLine.cs b/src/LogExpert/Classes/CommandLine/ConsoleCmdLine.cs index 80474c83..408831e5 100644 --- a/src/LogExpert/Classes/CommandLine/ConsoleCmdLine.cs +++ b/src/LogExpert/Classes/CommandLine/ConsoleCmdLine.cs @@ -5,57 +5,56 @@ //TODO: Replace with https://github.com/commandlineparser/commandline //TODO: or with this https://github.com/natemcmaster/CommandLineUtils -namespace LogExpert.Classes.CommandLine +namespace LogExpert.Classes.CommandLine; + +/// +/// Represents a CmdLine object to use with console applications. +/// The -help parameter will be registered automatically. +/// Any errors will be written to the console instead of generating exceptions. +/// +public class ConsoleCmdLine : CmdLine { - /// - /// Represents a CmdLine object to use with console applications. - /// The -help parameter will be registered automatically. - /// Any errors will be written to the console instead of generating exceptions. - /// - public class ConsoleCmdLine : CmdLine + #region cTor + + public ConsoleCmdLine() { - #region cTor + RegisterParameter(new CmdLineString("help", false, "Prints the help screen.")); + } + + #endregion + + #region Public methods + + public new string[] Parse(string[] args) + { + string[] ret = []; + + var error = string.Empty; - public ConsoleCmdLine() + try { - RegisterParameter(new CmdLineString("help", false, "Prints the help screen.")); + ret = base.Parse(args); + } + catch (CmdLineException ex) + { + error = ex.Message; } - #endregion - - #region Public methods + if (this["help"].Exists) + { + Console.WriteLine(HelpScreen()); + Environment.Exit(0); + } - public new string[] Parse(string[] args) + if (error != string.Empty) { - string[] ret = []; - - string error = string.Empty; - - try - { - ret = base.Parse(args); - } - catch (CmdLineException ex) - { - error = ex.Message; - } - - if (this["help"].Exists) - { - Console.WriteLine(HelpScreen()); - Environment.Exit(0); - } - - if (error != string.Empty) - { - Console.WriteLine(error); - Console.WriteLine("Use -help for more information."); - Environment.Exit(1); - } - - return ret; + Console.WriteLine(error); + Console.WriteLine("Use -help for more information."); + Environment.Exit(1); } - #endregion + return ret; } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert/Classes/LogExpertApplicationContext.cs b/src/LogExpert/Classes/LogExpertApplicationContext.cs index 1dfc04e1..a078f898 100644 --- a/src/LogExpert/Classes/LogExpertApplicationContext.cs +++ b/src/LogExpert/Classes/LogExpertApplicationContext.cs @@ -2,35 +2,34 @@ using System; using System.Windows.Forms; -namespace LogExpert.Classes -{ - internal class LogExpertApplicationContext : ApplicationContext - { - #region Fields +namespace LogExpert.Classes; - private readonly LogExpertProxy _proxy; +internal class LogExpertApplicationContext : ApplicationContext +{ + #region Fields - #endregion + private readonly LogExpertProxy _proxy; - #region cTor + #endregion - public LogExpertApplicationContext(LogExpertProxy proxy, ILogTabWindow firstLogWin) - { - _proxy = proxy; - _proxy.LastWindowClosed += new LogExpertProxy.LastWindowClosedEventHandler(OnProxyLastWindowClosed); - firstLogWin.Show(); - } + #region cTor - #endregion + public LogExpertApplicationContext(LogExpertProxy proxy, ILogTabWindow firstLogWin) + { + _proxy = proxy; + _proxy.LastWindowClosed += new LogExpertProxy.LastWindowClosedEventHandler(OnProxyLastWindowClosed); + firstLogWin.Show(); + } - #region Events handler + #endregion - private void OnProxyLastWindowClosed(object sender, EventArgs e) - { - ExitThread(); - Application.Exit(); - } + #region Events handler - #endregion + private void OnProxyLastWindowClosed(object sender, EventArgs e) + { + ExitThread(); + Application.Exit(); } + + #endregion } \ No newline at end of file diff --git a/src/LogExpert/Classes/LogExpertProxy.cs b/src/LogExpert/Classes/LogExpertProxy.cs index 25f514f1..6823f7da 100644 --- a/src/LogExpert/Classes/LogExpertProxy.cs +++ b/src/LogExpert/Classes/LogExpertProxy.cs @@ -8,172 +8,171 @@ using System.Collections.Generic; using System.Windows.Forms; -namespace LogExpert.Classes +namespace LogExpert.Classes; + +internal class LogExpertProxy : ILogExpertProxy { - internal class LogExpertProxy : ILogExpertProxy - { - #region Fields + #region Fields - private static readonly Logger _logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger _logger = LogManager.GetCurrentClassLogger(); - [NonSerialized] private readonly List _windowList = []; + [NonSerialized] private readonly List _windowList = []; - [NonSerialized] private ILogTabWindow _firstLogTabWindow; + [NonSerialized] private ILogTabWindow _firstLogTabWindow; - [NonSerialized] private int _logWindowIndex = 1; + [NonSerialized] private int _logWindowIndex = 1; - #endregion + #endregion - #region cTor + #region cTor - public LogExpertProxy(ILogTabWindow logTabWindow) - { - AddWindow(logTabWindow); - logTabWindow.LogExpertProxy = this; - _firstLogTabWindow = logTabWindow; - } + public LogExpertProxy(ILogTabWindow logTabWindow) + { + AddWindow(logTabWindow); + logTabWindow.LogExpertProxy = this; + _firstLogTabWindow = logTabWindow; + } - #endregion + #endregion - #region Delegates + #region Delegates - //public void BroadcastSettingsChanged(Object cookie) - //{ - // lock (this.windowList) - // { - // foreach (LogTabWindow logTabWindow in this.windowList) - // { - // logTabWindow.NotifySettingsChanged(cookie); - // } - // } - //} + //public void BroadcastSettingsChanged(Object cookie) + //{ + // lock (this.windowList) + // { + // foreach (LogTabWindow logTabWindow in this.windowList) + // { + // logTabWindow.NotifySettingsChanged(cookie); + // } + // } + //} - public delegate void LastWindowClosedEventHandler(object sender, EventArgs e); + public delegate void LastWindowClosedEventHandler(object sender, EventArgs e); - #endregion + #endregion - #region Events + #region Events - public event LastWindowClosedEventHandler LastWindowClosed; + public event LastWindowClosedEventHandler LastWindowClosed; - #endregion + #endregion - #region Public methods + #region Public methods - public void LoadFiles(string[] fileNames) - { - _logger.Info("Loading files into existing LogTabWindow"); - ILogTabWindow logWin = _windowList[^1]; - _ = logWin.Invoke(new MethodInvoker(logWin.SetForeground)); - logWin.LoadFiles(fileNames); - } + public void LoadFiles(string[] fileNames) + { + _logger.Info("Loading files into existing LogTabWindow"); + ILogTabWindow logWin = _windowList[^1]; + _ = logWin.Invoke(new MethodInvoker(logWin.SetForeground)); + logWin.LoadFiles(fileNames); + } - public void NewWindow(string[] fileNames) + public void NewWindow(string[] fileNames) + { + if (_firstLogTabWindow.IsDisposed) { - if (_firstLogTabWindow.IsDisposed) + _logger.Warn("first GUI thread window is disposed. Setting a new one."); + // may occur if a window is closed because of unhandled exception. + // Determine a new 'firstWindow'. If no window is left, start a new one. + RemoveWindow(_firstLogTabWindow); + if (_windowList.Count == 0) { - _logger.Warn("first GUI thread window is disposed. Setting a new one."); - // may occur if a window is closed because of unhandled exception. - // Determine a new 'firstWindow'. If no window is left, start a new one. - RemoveWindow(_firstLogTabWindow); - if (_windowList.Count == 0) - { - _logger.Info("No windows left. New created window will be the new 'first' GUI window"); - LoadFiles(fileNames); - } - else - { - _firstLogTabWindow = _windowList[^1]; - NewWindow(fileNames); - } + _logger.Info("No windows left. New created window will be the new 'first' GUI window"); + LoadFiles(fileNames); } else { - _ = _firstLogTabWindow.Invoke(new NewWindowFx(NewWindowWorker), new object[] { fileNames }); + _firstLogTabWindow = _windowList[^1]; + NewWindow(fileNames); } } + else + { + _ = _firstLogTabWindow.Invoke(new NewWindowFx(NewWindowWorker), [fileNames]); + } + } - public void NewWindowOrLockedWindow(string[] fileNames) + public void NewWindowOrLockedWindow(string[] fileNames) + { + foreach (var logWin in _windowList) { - foreach (var logWin in _windowList) + if (AbstractLogTabWindow.StaticData.CurrentLockedMainWindow == logWin) { - if (AbstractLogTabWindow.StaticData.CurrentLockedMainWindow == logWin) - { - _ = logWin.Invoke(new MethodInvoker(logWin.SetForeground)); - logWin.LoadFiles(fileNames); - return; - } + _ = logWin.Invoke(new MethodInvoker(logWin.SetForeground)); + logWin.LoadFiles(fileNames); + return; } - // No locked window was found --> create a new one - NewWindow(fileNames); } + // No locked window was found --> create a new one + NewWindow(fileNames); + } - public void NewWindowWorker(string[] fileNames) - { - _logger.Info("Creating new LogTabWindow"); - IConfigManager configManager = ConfigManager.Instance; - ILogTabWindow logWin = AbstractLogTabWindow.Create(fileNames.Length > 0 ? fileNames : null, _logWindowIndex++, true, configManager); - logWin.LogExpertProxy = this; - AddWindow(logWin); - logWin.Show(); - logWin.Activate(); - } + public void NewWindowWorker(string[] fileNames) + { + _logger.Info("Creating new LogTabWindow"); + IConfigManager configManager = ConfigManager.Instance; + ILogTabWindow logWin = AbstractLogTabWindow.Create(fileNames.Length > 0 ? fileNames : null, _logWindowIndex++, true, configManager); + logWin.LogExpertProxy = this; + AddWindow(logWin); + logWin.Show(); + logWin.Activate(); + } - public void WindowClosed(ILogTabWindow logWin) + public void WindowClosed(ILogTabWindow logWin) + { + RemoveWindow(logWin); + if (_windowList.Count == 0) { - RemoveWindow(logWin); - if (_windowList.Count == 0) - { - _logger.Info("Last LogTabWindow was closed"); - PluginRegistry.PluginRegistry.Instance.CleanupPlugins(); - OnLastWindowClosed(); - } - else + _logger.Info("Last LogTabWindow was closed"); + PluginRegistry.PluginRegistry.Instance.CleanupPlugins(); + OnLastWindowClosed(); + } + else + { + if (_firstLogTabWindow == logWin) { - if (_firstLogTabWindow == logWin) - { - // valid firstLogTabWindow is needed for the Invoke()-Calls in NewWindow() - _firstLogTabWindow = _windowList[^1]; - } + // valid firstLogTabWindow is needed for the Invoke()-Calls in NewWindow() + _firstLogTabWindow = _windowList[^1]; } } + } - public int GetLogWindowCount() - { - return _windowList.Count; - } + public int GetLogWindowCount() + { + return _windowList.Count; + } - //public override object InitializeLifetimeService() - //{ - // return null; - //} + //public override object InitializeLifetimeService() + //{ + // return null; + //} - #endregion + #endregion - #region Private Methods + #region Private Methods - private void AddWindow(ILogTabWindow window) - { - _logger.Info("Adding window to list"); - _windowList.Add(window); - } - - private void RemoveWindow(ILogTabWindow window) - { - _logger.Info("Removing window from list"); - _ = _windowList.Remove(window); - } + private void AddWindow(ILogTabWindow window) + { + _logger.Info("Adding window to list"); + _windowList.Add(window); + } - #endregion + private void RemoveWindow(ILogTabWindow window) + { + _logger.Info("Removing window from list"); + _ = _windowList.Remove(window); + } - protected void OnLastWindowClosed() - { - LastWindowClosed?.Invoke(this, new EventArgs()); - } + #endregion - private delegate void NewWindowFx(string[] fileNames); + protected void OnLastWindowClosed() + { + LastWindowClosed?.Invoke(this, new EventArgs()); } + + private delegate void NewWindowFx(string[] fileNames); } \ No newline at end of file diff --git a/src/LogExpert/Config/ConfigManager.cs b/src/LogExpert/Config/ConfigManager.cs index 28efa83f..939860b4 100644 --- a/src/LogExpert/Config/ConfigManager.cs +++ b/src/LogExpert/Config/ConfigManager.cs @@ -1,3 +1,8 @@ +using System.Drawing; +using System.Reflection; +using System.Text; +using System.Windows.Forms; + using LogExpert.Core.Classes; using LogExpert.Core.Classes.Filter; using LogExpert.Core.Config; @@ -5,430 +10,421 @@ using LogExpert.Core.EventArguments; using LogExpert.Core.EventHandlers; using LogExpert.Core.Interface; + using Newtonsoft.Json; using NLog; -using System; -using System.Collections.Generic; -using System.Drawing; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Windows.Forms; +namespace LogExpert.Config; -namespace LogExpert.Config +public class ConfigManager : IConfigManager { - public class ConfigManager : IConfigManager - { - #region Fields + #region Fields - private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); + private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); - private static readonly object _monitor = new(); - private static ConfigManager _instance; - private readonly object _loadSaveLock = new(); - private Settings _settings; + private static readonly object _monitor = new(); + private static ConfigManager _instance; + private readonly object _loadSaveLock = new(); + private Settings _settings; - #endregion + #endregion - #region cTor + #region cTor - private ConfigManager() - { - _settings = Load(); - } + private ConfigManager () + { + _settings = Load(); + } - #endregion + #endregion - #region Events + #region Events - public event ConfigChangedEventHandler ConfigChanged; + public event ConfigChangedEventHandler ConfigChanged; - #endregion + #endregion - #region Properties + #region Properties - public static ConfigManager Instance + public static ConfigManager Instance + { + get { - get + lock (_monitor) { - lock (_monitor) - { - _instance ??= new ConfigManager(); - } - return _instance; + _instance ??= new ConfigManager(); } + return _instance; } + } + + public string ConfigDir => Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + Path.DirectorySeparatorChar + "LogExpert"; //TODO: change to Path.Combine + + /// + /// Application.StartupPath + portable + /// + public string PortableModeDir => Application.StartupPath + Path.DirectorySeparatorChar + "portable"; + + /// + /// portableMode.json + /// + public string PortableModeSettingsFileName => "portableMode.json"; + + public Settings Settings => Instance._settings; - public string ConfigDir => Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + Path.DirectorySeparatorChar + "LogExpert"; //TODO: change to Path.Combine + IConfigManager IConfigManager.Instance => Instance; - /// - /// Application.StartupPath + portable - /// - public string PortableModeDir => Application.StartupPath + Path.DirectorySeparatorChar + "portable"; + // Action IConfigManager.ConfigChanged { get => ((IConfigManager)_instance).ConfigChanged; set => ((IConfigManager)_instance).ConfigChanged = value; } - /// - /// portableMode.json - /// - public string PortableModeSettingsFileName => "portableMode.json"; + //public string PortableModeSettingsFileName => ((IConfigManager)_instance).PortableModeSettingsFileName; - public Settings Settings => Instance._settings; + #endregion - IConfigManager IConfigManager.Instance => Instance; + #region Public methods -// Action IConfigManager.ConfigChanged { get => ((IConfigManager)_instance).ConfigChanged; set => ((IConfigManager)_instance).ConfigChanged = value; } + public void Save (SettingsFlags flags) + { + Instance.Save(Settings, flags); + } + + public void Export (FileInfo fileInfo) + { + Instance.Save(fileInfo, Settings); + } + + public void Export (FileInfo fileInfo, SettingsFlags flags) + { + Instance.Save(fileInfo, Settings, flags); + } - //public string PortableModeSettingsFileName => ((IConfigManager)_instance).PortableModeSettingsFileName; + public void Import (FileInfo fileInfo, ExportImportFlags flags) + { + Instance._settings = Instance.Import(Instance._settings, fileInfo, flags); + Save(SettingsFlags.All); + } - #endregion + public void ImportHighlightSettings (FileInfo fileInfo, ExportImportFlags flags) + { + Instance._settings.Preferences.HighlightGroupList = Instance.Import(Instance._settings.Preferences.HighlightGroupList, fileInfo, flags); + Save(SettingsFlags.All); + } - #region Public methods + #endregion - public void Save(SettingsFlags flags) + #region Private Methods + + private Settings Load () + { + _logger.Info("Loading settings"); + + string dir; + + if (File.Exists(PortableModeDir + Path.DirectorySeparatorChar + PortableModeSettingsFileName) == false) { - Instance.Save(Settings, flags); + _logger.Info("Load settings standard mode"); + dir = ConfigDir; } - - public void Export(FileInfo fileInfo) + else { - Instance.Save(fileInfo, Settings); + _logger.Info("Load settings portable mode"); + dir = Application.StartupPath; } - public void Export(FileInfo fileInfo, SettingsFlags flags) + if (!Directory.Exists(dir)) { - Instance.Save(fileInfo, Settings, flags); + Directory.CreateDirectory(dir); } - public void Import(FileInfo fileInfo, ExportImportFlags flags) + if (!File.Exists(dir + Path.DirectorySeparatorChar + "settings.json")) { - Instance._settings = Instance.Import(Instance._settings, fileInfo, flags); - Save(SettingsFlags.All); + return LoadOrCreateNew(null); } - public void ImportHighlightSettings(FileInfo fileInfo, ExportImportFlags flags) + try { - Instance._settings.Preferences.HighlightGroupList = Instance.Import(Instance._settings.Preferences.HighlightGroupList, fileInfo, flags); - Save(SettingsFlags.All); + FileInfo fileInfo = new(dir + Path.DirectorySeparatorChar + "settings.json"); + return LoadOrCreateNew(fileInfo); + } + catch (Exception e) + { + _logger.Error($"Error loading settings: {e}"); + return LoadOrCreateNew(null); } - #endregion - - #region Private Methods + } - private Settings Load() + /// + /// Loads Settings of a given file or creates new settings if the file does not exist + /// + /// file that has settings saved + /// loaded or created settings + private Settings LoadOrCreateNew (FileInfo fileInfo) + { + lock (_loadSaveLock) { - _logger.Info("Loading settings"); - - string dir; + Settings settings; - if (File.Exists(PortableModeDir + Path.DirectorySeparatorChar + PortableModeSettingsFileName) == false) + if (fileInfo == null || fileInfo.Exists == false) { - _logger.Info("Load settings standard mode"); - dir = ConfigDir; + settings = new Settings(); } else { - _logger.Info("Load settings portable mode"); - dir = Application.StartupPath; + try + { + settings = JsonConvert.DeserializeObject(File.ReadAllText($"{fileInfo.FullName}")); + } + catch (Exception e) + { + _logger.Error($"Error while deserializing config data: {e}"); + settings = new Settings(); + } } - if (!Directory.Exists(dir)) - { - Directory.CreateDirectory(dir); - } + settings.Preferences ??= new Preferences(); + + settings.Preferences.toolEntries ??= []; + + settings.Preferences.columnizerMaskList ??= []; + + settings.fileHistoryList ??= []; + + settings.lastOpenFilesList ??= []; + + settings.fileColors ??= []; - if (!File.Exists(dir + Path.DirectorySeparatorChar + "settings.json")) + if (settings.Preferences.showTailColor == Color.Empty) { - return LoadOrCreateNew(null); + settings.Preferences.showTailColor = Color.FromKnownColor(KnownColor.Blue); } - try + if (settings.Preferences.timeSpreadColor == Color.Empty) { - FileInfo fileInfo = new(dir + Path.DirectorySeparatorChar + "settings.json"); - return LoadOrCreateNew(fileInfo); + settings.Preferences.timeSpreadColor = Color.Gray; } - catch (Exception e) + + if (settings.Preferences.bufferCount < 10) { - _logger.Error($"Error loading settings: {e}"); - return LoadOrCreateNew(null); + settings.Preferences.bufferCount = 100; } - } - - /// - /// Loads Settings of a given file or creates new settings if the file does not exist - /// - /// file that has settings saved - /// loaded or created settings - private Settings LoadOrCreateNew(FileInfo fileInfo) - { - lock (_loadSaveLock) + if (settings.Preferences.linesPerBuffer < 1) { - Settings settings; + settings.Preferences.linesPerBuffer = 500; + } - if (fileInfo == null || fileInfo.Exists == false) - { - settings = new Settings(); - } - else - { - try - { - settings = JsonConvert.DeserializeObject(File.ReadAllText($"{fileInfo.FullName}")); - } - catch (Exception e) - { - _logger.Error($"Error while deserializing config data: {e}"); - settings = new Settings(); - } - } + settings.filterList ??= []; - settings.Preferences ??= new Preferences(); + settings.searchHistoryList ??= []; - settings.Preferences.toolEntries ??= []; + settings.filterHistoryList ??= []; - settings.Preferences.columnizerMaskList ??= []; + settings.filterRangeHistoryList ??= []; - settings.fileHistoryList ??= []; + foreach (FilterParams filterParams in settings.filterList) + { + filterParams.Init(); + } - settings.lastOpenFilesList ??= []; + if (settings.Preferences.HighlightGroupList == null) + { + settings.Preferences.HighlightGroupList = []; + } - settings.fileColors ??= []; + settings.Preferences.highlightMaskList ??= []; - if (settings.Preferences.showTailColor == Color.Empty) - { - settings.Preferences.showTailColor = Color.FromKnownColor(KnownColor.Blue); - } + if (settings.Preferences.pollingInterval < 20) + { + settings.Preferences.pollingInterval = 250; + } - if (settings.Preferences.timeSpreadColor == Color.Empty) - { - settings.Preferences.timeSpreadColor = Color.Gray; - } + settings.Preferences.multiFileOptions ??= new MultiFileOptions(); - if (settings.Preferences.bufferCount < 10) - { - settings.Preferences.bufferCount = 100; - } + settings.Preferences.defaultEncoding ??= Encoding.Default.HeaderName; - if (settings.Preferences.linesPerBuffer < 1) - { - settings.Preferences.linesPerBuffer = 500; - } + if (settings.Preferences.maximumFilterEntriesDisplayed == 0) + { + settings.Preferences.maximumFilterEntriesDisplayed = 20; + } - settings.filterList ??= []; + if (settings.Preferences.maximumFilterEntries == 0) + { + settings.Preferences.maximumFilterEntries = 30; + } - settings.searchHistoryList ??= []; + SetBoundsWithinVirtualScreen(settings); - settings.filterHistoryList ??= []; + return settings; + } + } - settings.filterRangeHistoryList ??= []; + /// + /// Saves the Settings to file, fires OnConfigChanged Event so LogTabWindow is updated + /// + /// Settings to be saved + /// Settings that "changed" + private void Save (Settings settings, SettingsFlags flags) + { + lock (_loadSaveLock) + { + _logger.Info("Saving settings"); + lock (this) + { + var dir = Settings.Preferences.PortableMode ? Application.StartupPath : ConfigDir; - foreach (FilterParams filterParams in settings.filterList) + if (!Directory.Exists(dir)) { - filterParams.Init(); + Directory.CreateDirectory(dir); } - if (settings.Preferences.HighlightGroupList == null) - { - settings.Preferences.HighlightGroupList = []; - } + FileInfo fileInfo = new(dir + Path.DirectorySeparatorChar + "settings.json"); + Save(fileInfo, settings); + } - settings.Preferences.highlightMaskList ??= []; + OnConfigChanged(flags); + } + } - if (settings.Preferences.pollingInterval < 20) - { - settings.Preferences.pollingInterval = 250; - } + /// + /// Saves the file in any defined format + /// + /// FileInfo for creating the file (if exists will be overwritten) + /// Current Settings + private void Save (FileInfo fileInfo, Settings settings) + { + //Currently only fileFormat, maybe add some other formats later (YAML or XML?) + SaveAsJSON(fileInfo, settings); + } - settings.Preferences.multiFileOptions ??= new MultiFileOptions(); + private void Save (FileInfo fileInfo, Settings settings, SettingsFlags flags) + { + switch (flags) + { + case SettingsFlags.HighlightSettings: + SaveHighlightgroupsAsJSON(fileInfo, settings.Preferences.HighlightGroupList); + break; + } - settings.Preferences.defaultEncoding ??= Encoding.Default.HeaderName; + OnConfigChanged(flags); + } - if (settings.Preferences.maximumFilterEntriesDisplayed == 0) - { - settings.Preferences.maximumFilterEntriesDisplayed = 20; - } + private static void SaveAsJSON (FileInfo fileInfo, Settings settings) + { + settings.versionBuild = Assembly.GetExecutingAssembly().GetName().Version.Build; - if (settings.Preferences.maximumFilterEntries == 0) - { - settings.Preferences.maximumFilterEntries = 30; - } + using StreamWriter sw = new(fileInfo.Create()); + JsonSerializer serializer = new(); + serializer.Serialize(sw, settings); + } + + private static void SaveHighlightgroupsAsJSON (FileInfo fileInfo, List groups) + { + using StreamWriter sw = new(fileInfo.Create()); + JsonSerializer serializer = new(); + serializer.Serialize(sw, groups); + } - SetBoundsWithinVirtualScreen(settings); + private List Import (List currentGroups, FileInfo fileInfo, ExportImportFlags flags) + { + List newGroups; - return settings; - } + try + { + newGroups = JsonConvert.DeserializeObject>(File.ReadAllText($"{fileInfo.FullName}")); } - - /// - /// Saves the Settings to file, fires OnConfigChanged Event so LogTabWindow is updated - /// - /// Settings to be saved - /// Settings that "changed" - private void Save(Settings settings, SettingsFlags flags) + catch (Exception e) { - lock (_loadSaveLock) - { - _logger.Info("Saving settings"); - lock (this) - { - string dir = Settings.Preferences.PortableMode ? Application.StartupPath : ConfigDir; - - if (!Directory.Exists(dir)) - { - Directory.CreateDirectory(dir); - } - - FileInfo fileInfo = new(dir + Path.DirectorySeparatorChar + "settings.json"); - Save(fileInfo, settings); - } - - OnConfigChanged(flags); - } + _logger.Error($"Error while deserializing config data: {e}"); + newGroups = []; } - /// - /// Saves the file in any defined format - /// - /// FileInfo for creating the file (if exists will be overwritten) - /// Current Settings - private void Save(FileInfo fileInfo, Settings settings) + if (flags.HasFlag(ExportImportFlags.KeepExisting)) { - //Currently only fileFormat, maybe add some other formats later (YAML or XML?) - SaveAsJSON(fileInfo, settings); + currentGroups.AddRange(newGroups); } - - private void Save(FileInfo fileInfo, Settings settings, SettingsFlags flags) + else { - switch (flags) - { - case SettingsFlags.HighlightSettings: - SaveHighlightgroupsAsJSON(fileInfo, settings.Preferences.HighlightGroupList); - break; - } - - OnConfigChanged(flags); + currentGroups.Clear(); + currentGroups.AddRange(newGroups); } - private static void SaveAsJSON(FileInfo fileInfo, Settings settings) - { - settings.versionBuild = Assembly.GetExecutingAssembly().GetName().Version.Build; + return currentGroups; + } - using StreamWriter sw = new(fileInfo.Create()); - JsonSerializer serializer = new(); - serializer.Serialize(sw, settings); - } + /// + /// Imports all or some of the settings/prefs stored in the input stream. + /// This will overwrite appropriate parts of the current (own) settings with the imported ones. + /// + /// + /// + /// Flags to indicate which parts shall be imported + private Settings Import (Settings currentSettings, FileInfo fileInfo, ExportImportFlags flags) + { + Settings importSettings = LoadOrCreateNew(fileInfo); + Settings ownSettings = ObjectClone.Clone(currentSettings); + Settings newSettings; - private static void SaveHighlightgroupsAsJSON(FileInfo fileInfo, List groups) + // at first check for 'Other' as this are the most options. + if ((flags & ExportImportFlags.Other) == ExportImportFlags.Other) { - using StreamWriter sw = new(fileInfo.Create()); - JsonSerializer serializer = new(); - serializer.Serialize(sw, groups); + newSettings = ownSettings; + newSettings.Preferences = ObjectClone.Clone(importSettings.Preferences); + newSettings.Preferences.columnizerMaskList = ownSettings.Preferences.columnizerMaskList; + newSettings.Preferences.highlightMaskList = ownSettings.Preferences.highlightMaskList; + newSettings.Preferences.HighlightGroupList = ownSettings.Preferences.HighlightGroupList; + newSettings.Preferences.toolEntries = ownSettings.Preferences.toolEntries; } - - private List Import(List currentGroups, FileInfo fileInfo, ExportImportFlags flags) + else { - List newGroups; - - try - { - newGroups = JsonConvert.DeserializeObject>(File.ReadAllText($"{fileInfo.FullName}")); - } - catch (Exception e) - { - _logger.Error($"Error while deserializing config data: {e}"); - newGroups = []; - } - - if (flags.HasFlag(ExportImportFlags.KeepExisting)) - { - currentGroups.AddRange(newGroups); - } - else - { - currentGroups.Clear(); - currentGroups.AddRange(newGroups); - } - - return currentGroups; + newSettings = ownSettings; } - /// - /// Imports all or some of the settings/prefs stored in the input stream. - /// This will overwrite appropriate parts of the current (own) settings with the imported ones. - /// - /// - /// - /// Flags to indicate which parts shall be imported - private Settings Import(Settings currentSettings, FileInfo fileInfo, ExportImportFlags flags) + if ((flags & ExportImportFlags.ColumnizerMasks) == ExportImportFlags.ColumnizerMasks) { - Settings importSettings = LoadOrCreateNew(fileInfo); - Settings ownSettings = ObjectClone.Clone(currentSettings); - Settings newSettings; - - // at first check for 'Other' as this are the most options. - if ((flags & ExportImportFlags.Other) == ExportImportFlags.Other) - { - newSettings = ownSettings; - newSettings.Preferences = ObjectClone.Clone(importSettings.Preferences); - newSettings.Preferences.columnizerMaskList = ownSettings.Preferences.columnizerMaskList; - newSettings.Preferences.highlightMaskList = ownSettings.Preferences.highlightMaskList; - newSettings.Preferences.HighlightGroupList = ownSettings.Preferences.HighlightGroupList; - newSettings.Preferences.toolEntries = ownSettings.Preferences.toolEntries; - } - else - { - newSettings = ownSettings; - } - - if ((flags & ExportImportFlags.ColumnizerMasks) == ExportImportFlags.ColumnizerMasks) - { - newSettings.Preferences.columnizerMaskList = ReplaceOrKeepExisting(flags, ownSettings.Preferences.columnizerMaskList, importSettings.Preferences.columnizerMaskList); - } - if ((flags & ExportImportFlags.HighlightMasks) == ExportImportFlags.HighlightMasks) - { - newSettings.Preferences.highlightMaskList = ReplaceOrKeepExisting(flags, ownSettings.Preferences.highlightMaskList, importSettings.Preferences.highlightMaskList); - } - if ((flags & ExportImportFlags.HighlightSettings) == ExportImportFlags.HighlightSettings) - { - newSettings.Preferences.HighlightGroupList = ReplaceOrKeepExisting(flags, ownSettings.Preferences.HighlightGroupList, importSettings.Preferences.HighlightGroupList); - } - if ((flags & ExportImportFlags.ToolEntries) == ExportImportFlags.ToolEntries) - { - newSettings.Preferences.toolEntries = ReplaceOrKeepExisting(flags, ownSettings.Preferences.toolEntries, importSettings.Preferences.toolEntries); - } - - return newSettings; + newSettings.Preferences.columnizerMaskList = ReplaceOrKeepExisting(flags, ownSettings.Preferences.columnizerMaskList, importSettings.Preferences.columnizerMaskList); } - - private static List ReplaceOrKeepExisting(ExportImportFlags flags, List existingList, List newList) + if ((flags & ExportImportFlags.HighlightMasks) == ExportImportFlags.HighlightMasks) { - if ((flags & ExportImportFlags.KeepExisting) == ExportImportFlags.KeepExisting) - { - return existingList.Union(newList).ToList(); - } - - return newList; + newSettings.Preferences.highlightMaskList = ReplaceOrKeepExisting(flags, ownSettings.Preferences.highlightMaskList, importSettings.Preferences.highlightMaskList); + } + if ((flags & ExportImportFlags.HighlightSettings) == ExportImportFlags.HighlightSettings) + { + newSettings.Preferences.HighlightGroupList = ReplaceOrKeepExisting(flags, ownSettings.Preferences.HighlightGroupList, importSettings.Preferences.HighlightGroupList); + } + if ((flags & ExportImportFlags.ToolEntries) == ExportImportFlags.ToolEntries) + { + newSettings.Preferences.toolEntries = ReplaceOrKeepExisting(flags, ownSettings.Preferences.toolEntries, importSettings.Preferences.toolEntries); } - // Checking if the appBounds values are outside the current virtual screen. - // If so, the appBounds values are set to 0. - private void SetBoundsWithinVirtualScreen(Settings settings) + return newSettings; + } + + private static List ReplaceOrKeepExisting (ExportImportFlags flags, List existingList, List newList) + { + if ((flags & ExportImportFlags.KeepExisting) == ExportImportFlags.KeepExisting) { - var vs = SystemInformation.VirtualScreen; - if (vs.X + vs.Width < settings.appBounds.X + settings.appBounds.Width || - vs.Y + vs.Height < settings.appBounds.Y + settings.appBounds.Height) - { - settings.appBounds = new Rectangle(); - } + return existingList.Union(newList).ToList(); } - #endregion - protected void OnConfigChanged(SettingsFlags flags) + return newList; + } + + // Checking if the appBounds values are outside the current virtual screen. + // If so, the appBounds values are set to 0. + private void SetBoundsWithinVirtualScreen (Settings settings) + { + var vs = SystemInformation.VirtualScreen; + if (vs.X + vs.Width < settings.appBounds.X + settings.appBounds.Width || + vs.Y + vs.Height < settings.appBounds.Y + settings.appBounds.Height) { - ConfigChanged?.Invoke(this, new ConfigChangedEventArgs(flags)); + settings.appBounds = new Rectangle(); } } + #endregion + + protected void OnConfigChanged (SettingsFlags flags) + { + ConfigChanged?.Invoke(this, new ConfigChangedEventArgs(flags)); + } } \ No newline at end of file diff --git a/src/LogExpert/Program.cs b/src/LogExpert/Program.cs index 347bc900..17226642 100644 --- a/src/LogExpert/Program.cs +++ b/src/LogExpert/Program.cs @@ -21,344 +21,343 @@ using System.Text; using System.Windows.Forms; -namespace LogExpert +namespace LogExpert; + +internal static class Program { - internal static class Program - { - #region Fields + #region Fields - private static readonly Logger _logger = LogManager.GetLogger("Program"); - private const string PIPE_SERVER_NAME = "LogExpert_IPC"; - private const int PIPE_CONNECTION_TIMEOUT_IN_MS = 5000; + private static readonly Logger _logger = LogManager.GetLogger("Program"); + private const string PIPE_SERVER_NAME = "LogExpert_IPC"; + private const int PIPE_CONNECTION_TIMEOUT_IN_MS = 5000; - #endregion + #endregion - #region Private Methods + #region Private Methods - /// - /// The main entry point for the application. - /// - [STAThread] - private static void Main(string[] args) - { - AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; - Application.ThreadException += Application_ThreadException; + /// + /// The main entry point for the application. + /// + [STAThread] + private static void Main(string[] args) + { + AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; + Application.ThreadException += Application_ThreadException; - ApplicationConfiguration.Initialize(); + ApplicationConfiguration.Initialize(); - Application.EnableVisualStyles(); - Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); + Application.EnableVisualStyles(); + Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); - _logger.Info("\r\n============================================================================\r\nLogExpert {0} started.\r\n============================================================================", Assembly.GetExecutingAssembly().GetName().Version.ToString(3)); + _logger.Info("\r\n============================================================================\r\nLogExpert {0} started.\r\n============================================================================", Assembly.GetExecutingAssembly().GetName().Version.ToString(3)); - CancellationTokenSource cts = new(); - try + CancellationTokenSource cts = new(); + try + { + CmdLineString configFile = new("config", false, "A configuration (settings) file"); + CmdLine cmdLine = new(); + cmdLine.RegisterParameter(configFile); + if (configFile.Exists) { - CmdLineString configFile = new("config", false, "A configuration (settings) file"); - CmdLine cmdLine = new(); - cmdLine.RegisterParameter(configFile); - if (configFile.Exists) + FileInfo cfgFileInfo = new(configFile.Value); + //TODO: The config file import and the try catch for the primary instance and secondary instance should be separated functions + if (cfgFileInfo.Exists) { - FileInfo cfgFileInfo = new(configFile.Value); - //TODO: The config file import and the try catch for the primary instance and secondary instance should be separated functions - if (cfgFileInfo.Exists) - { - ConfigManager.Instance.Import(cfgFileInfo, ExportImportFlags.All); - } - else - { - MessageBox.Show(@"Config file not found", @"LogExpert"); - } + ConfigManager.Instance.Import(cfgFileInfo, ExportImportFlags.All); + } + else + { + MessageBox.Show(@"Config file not found", @"LogExpert"); } - PluginRegistry.PluginRegistry.Instance.Create(ConfigManager.Instance.ConfigDir, ConfigManager.Instance.Settings.Preferences.pollingInterval); + } + PluginRegistry.PluginRegistry.Instance.Create(ConfigManager.Instance.ConfigDir, ConfigManager.Instance.Settings.Preferences.pollingInterval); + + var pId = Process.GetCurrentProcess().SessionId; - var pId = Process.GetCurrentProcess().SessionId; + try + { + Mutex mutex = new(false, "Local\\LogExpertInstanceMutex" + pId, out var isCreated); + var remainingArgs = cmdLine.Parse(args); + var absoluteFilePaths = GenerateAbsoluteFilePaths(remainingArgs); - try + if (isCreated) { - Mutex mutex = new(false, "Local\\LogExpertInstanceMutex" + pId, out var isCreated); - var remainingArgs = cmdLine.Parse(args); - var absoluteFilePaths = GenerateAbsoluteFilePaths(remainingArgs); + // first application instance + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + ILogTabWindow logWin = AbstractLogTabWindow.Create(absoluteFilePaths.Length > 0 ? absoluteFilePaths : null, 1, false, ConfigManager.Instance); - if (isCreated) - { - // first application instance - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - ILogTabWindow logWin = AbstractLogTabWindow.Create(absoluteFilePaths.Length > 0 ? absoluteFilePaths : null, 1, false, ConfigManager.Instance); + // first instance + var wi = WindowsIdentity.GetCurrent(); + LogExpertProxy proxy = new(logWin); + LogExpertApplicationContext context = new(proxy, logWin); - // first instance - var wi = WindowsIdentity.GetCurrent(); - LogExpertProxy proxy = new(logWin); - LogExpertApplicationContext context = new(proxy, logWin); + Task.Run(() => RunServerLoopAsync(SendMessageToProxy, proxy, cts.Token)); - Task.Run(() => RunServerLoopAsync(SendMessageToProxy, proxy, cts.Token)); + Application.Run(context); + } + else + { + var counter = 3; + Exception errMsg = null; - Application.Run(context); - } - else + Settings settings = ConfigManager.Instance.Settings; + while (counter > 0) { - int counter = 3; - Exception errMsg = null; - - Settings settings = ConfigManager.Instance.Settings; - while (counter > 0) + try { - try - { - WindowsIdentity wi = WindowsIdentity.GetCurrent(); - var command = SerializeCommandIntoNonFormattedJSON(absoluteFilePaths, settings.Preferences.allowOnlyOneInstance); - SendCommandToServer(command); - break; - } - catch (Exception e) - { - _logger.Warn(e, "IpcClientChannel error: "); - errMsg = e; - counter--; - Thread.Sleep(500); - } + var wi = WindowsIdentity.GetCurrent(); + var command = SerializeCommandIntoNonFormattedJSON(absoluteFilePaths, settings.Preferences.allowOnlyOneInstance); + SendCommandToServer(command); + break; } - - if (counter == 0) + catch (Exception e) { - _logger.Error(errMsg, "IpcClientChannel error, giving up: "); - MessageBox.Show($"Cannot open connection to first instance ({errMsg})", "LogExpert"); + _logger.Warn(e, "IpcClientChannel error: "); + errMsg = e; + counter--; + Thread.Sleep(500); } + } + + if (counter == 0) + { + _logger.Error(errMsg, "IpcClientChannel error, giving up: "); + MessageBox.Show($"Cannot open connection to first instance ({errMsg})", "LogExpert"); + } - if (settings.Preferences.allowOnlyOneInstance && settings.Preferences.ShowErrorMessageAllowOnlyOneInstances) + if (settings.Preferences.allowOnlyOneInstance && settings.Preferences.ShowErrorMessageAllowOnlyOneInstances) + { + AllowOnlyOneInstanceErrorDialog a = new(); + if (a.ShowDialog() == DialogResult.OK) { - AllowOnlyOneInstanceErrorDialog a = new(); - if (a.ShowDialog() == DialogResult.OK) - { - settings.Preferences.ShowErrorMessageAllowOnlyOneInstances = !a.DoNotShowThisMessageAgain; - ConfigManager.Instance.Save(SettingsFlags.All); - } + settings.Preferences.ShowErrorMessageAllowOnlyOneInstances = !a.DoNotShowThisMessageAgain; + ConfigManager.Instance.Save(SettingsFlags.All); } } - - mutex.Close(); - cts.Cancel(); - } - catch (Exception ex) - { - _logger.Error(ex, "Mutex error, giving up: "); - cts.Cancel(); - MessageBox.Show($"Cannot open connection to first instance ({ex.Message})", "LogExpert"); } + + mutex.Close(); + cts.Cancel(); } - catch (SecurityException se) + catch (Exception ex) { - MessageBox.Show("Insufficient system rights for LogExpert. Maybe you have started it from a network drive. Please start LogExpert from a local drive.\n(" + se.Message + ")", "LogExpert Error"); + _logger.Error(ex, "Mutex error, giving up: "); cts.Cancel(); + MessageBox.Show($"Cannot open connection to first instance ({ex.Message})", "LogExpert"); } } - - private static string SerializeCommandIntoNonFormattedJSON(string[] fileNames, bool allowOnlyOneInstance) + catch (SecurityException se) { - var message = new IpcMessage() - { - Type = allowOnlyOneInstance ? IpcMessageType.NewWindowOrLockedWindow : IpcMessageType.NewWindow, - Payload = JObject.FromObject(new LoadPayload { Files = [.. fileNames] }) - }; - - return JsonConvert.SerializeObject(message, Formatting.None); + MessageBox.Show("Insufficient system rights for LogExpert. Maybe you have started it from a network drive. Please start LogExpert from a local drive.\n(" + se.Message + ")", "LogExpert Error"); + cts.Cancel(); } + } - // This loop tries to convert relative file names into absolute file names (assuming that platform file names are given). - // It tolerates errors, to give file system plugins (e.g. sftp) a change later. - // TODO: possibly should be moved to LocalFileSystem plugin - private static string[] GenerateAbsoluteFilePaths(string[] remainingArgs) + private static string SerializeCommandIntoNonFormattedJSON(string[] fileNames, bool allowOnlyOneInstance) + { + var message = new IpcMessage() { - List argsList = []; + Type = allowOnlyOneInstance ? IpcMessageType.NewWindowOrLockedWindow : IpcMessageType.NewWindow, + Payload = JObject.FromObject(new LoadPayload { Files = [.. fileNames] }) + }; + + return JsonConvert.SerializeObject(message, Formatting.None); + } + + // This loop tries to convert relative file names into absolute file names (assuming that platform file names are given). + // It tolerates errors, to give file system plugins (e.g. sftp) a change later. + // TODO: possibly should be moved to LocalFileSystem plugin + private static string[] GenerateAbsoluteFilePaths(string[] remainingArgs) + { + List argsList = []; - foreach (string fileArg in remainingArgs) + foreach (var fileArg in remainingArgs) + { + try { - try - { - FileInfo info = new(fileArg); - argsList.Add(info.Exists ? info.FullName : fileArg); - } - catch (Exception) - { - argsList.Add(fileArg); - } + FileInfo info = new(fileArg); + argsList.Add(info.Exists ? info.FullName : fileArg); + } + catch (Exception) + { + argsList.Add(fileArg); } - - return [.. argsList]; } - private static void SendMessageToProxy(IpcMessage message, LogExpertProxy proxy) + return [.. argsList]; + } + + private static void SendMessageToProxy(IpcMessage message, LogExpertProxy proxy) + { + switch (message.Type) { - switch (message.Type) - { - case IpcMessageType.Load: - { - var payLoad = message.Payload.ToObject(); + case IpcMessageType.Load: + { + var payLoad = message.Payload.ToObject(); - if (CheckPayload(payLoad)) - { - proxy.LoadFiles([.. payLoad.Files]); - } + if (CheckPayload(payLoad)) + { + proxy.LoadFiles([.. payLoad.Files]); } - break; - case IpcMessageType.NewWindow: + } + break; + case IpcMessageType.NewWindow: + { + var payLoad = message.Payload.ToObject(); + if (CheckPayload(payLoad)) { - var payLoad = message.Payload.ToObject(); - if (CheckPayload(payLoad)) - { - proxy.NewWindow([.. payLoad.Files]); - } + proxy.NewWindow([.. payLoad.Files]); } - break; - case IpcMessageType.NewWindowOrLockedWindow: + } + break; + case IpcMessageType.NewWindowOrLockedWindow: + { + var payLoad = message.Payload.ToObject(); + if (CheckPayload(payLoad)) { - var payLoad = message.Payload.ToObject(); - if (CheckPayload(payLoad)) - { - proxy.NewWindowOrLockedWindow([.. payLoad.Files]); - } + proxy.NewWindowOrLockedWindow([.. payLoad.Files]); } - break; - default: - _logger.Error($"Unknown IPC Message Type {message.Type}"); - break; - } + } + break; + default: + _logger.Error($"Unknown IPC Message Type {message.Type}"); + break; } + } - private static bool CheckPayload(LoadPayload payLoad) + private static bool CheckPayload(LoadPayload payLoad) + { + if (payLoad == null) { - if (payLoad == null) - { - _logger.Error("Invalid payload for NewWindow command"); - return false; - } + _logger.Error("Invalid payload for NewWindow command"); + return false; + } + + return true; + } - return true; + private static void SendCommandToServer(string command) + { + using var client = new NamedPipeClientStream(".", PIPE_SERVER_NAME, PipeDirection.Out); + + try + { + client.Connect(PIPE_CONNECTION_TIMEOUT_IN_MS); + } + catch (TimeoutException) + { + _logger.Error("Timeout connecting to pipe server"); + return; + } + catch (IOException ex) + { + _logger.Warn(ex, "An I/O error occurred while connecting to the pipe server."); + return; + } + catch (UnauthorizedAccessException ex) + { + _logger.Warn(ex, "Unauthorized access while connecting to the pipe server."); + return; } - private static void SendCommandToServer(string command) + using var writer = new StreamWriter(client, Encoding.UTF8) { AutoFlush = true }; + writer.WriteLine(command); + } + + private static async Task RunServerLoopAsync(Action onCommand, LogExpertProxy proxy, CancellationToken cancellationToken) + { + while (cancellationToken.IsCancellationRequested == false) { - using var client = new NamedPipeClientStream(".", PIPE_SERVER_NAME, PipeDirection.Out); + using var server = new NamedPipeServerStream( + PIPE_SERVER_NAME, + PipeDirection.In, + 1, + PipeTransmissionMode.Message, + PipeOptions.Asynchronous); try { - client.Connect(PIPE_CONNECTION_TIMEOUT_IN_MS); - } - catch (TimeoutException) - { - _logger.Error("Timeout connecting to pipe server"); - return; + await server.WaitForConnectionAsync(cancellationToken); + using var reader = new StreamReader(server, Encoding.UTF8); + var line = await reader.ReadLineAsync(cancellationToken); + + if (line != null) + { + var message = JsonConvert.DeserializeObject(line); + onCommand(message, proxy); + } } - catch (IOException ex) + catch (OperationCanceledException) { - _logger.Warn(ex, "An I/O error occurred while connecting to the pipe server."); - return; + break; } - catch (UnauthorizedAccessException ex) + catch (Exception ex) { - _logger.Warn(ex, "Unauthorized access while connecting to the pipe server."); - return; + _logger.Warn(ex, "Pipe server error"); } - - using var writer = new StreamWriter(client, Encoding.UTF8) { AutoFlush = true }; - writer.WriteLine(command); } + } - private static async Task RunServerLoopAsync(Action onCommand, LogExpertProxy proxy, CancellationToken cancellationToken) - { - while (cancellationToken.IsCancellationRequested == false) - { - using var server = new NamedPipeServerStream( - PIPE_SERVER_NAME, - PipeDirection.In, - 1, - PipeTransmissionMode.Message, - PipeOptions.Asynchronous); - - try - { - await server.WaitForConnectionAsync(cancellationToken); - using var reader = new StreamReader(server, Encoding.UTF8); - string line = await reader.ReadLineAsync(cancellationToken); + [STAThread] + private static void ShowUnhandledException(object exceptionObject) + { + var errorText = string.Empty; + string stackTrace; - if (line != null) - { - var message = JsonConvert.DeserializeObject(line); - onCommand(message, proxy); - } - } - catch (OperationCanceledException) - { - break; - } - catch (Exception ex) - { - _logger.Warn(ex, "Pipe server error"); - } - } + if (exceptionObject is Exception exception) + { + errorText = exception.Message; + stackTrace = $"\r\n{exception.GetType().Name}\r\n{exception.StackTrace}"; } - - [STAThread] - private static void ShowUnhandledException(object exceptionObject) + else { - string errorText = string.Empty; - string stackTrace; + stackTrace = exceptionObject.ToString(); + var lines = stackTrace.Split('\n'); - if (exceptionObject is Exception exception) - { - errorText = exception.Message; - stackTrace = $"\r\n{exception.GetType().Name}\r\n{exception.StackTrace}"; - } - else + if (lines != null && lines.Length > 0) { - stackTrace = exceptionObject.ToString(); - string[] lines = stackTrace.Split('\n'); - - if (lines != null && lines.Length > 0) - { - errorText = lines[0]; - } + errorText = lines[0]; } - - ExceptionWindow win = new(errorText, stackTrace); - _ = win.ShowDialog(); } - #endregion - - #region Events handler + ExceptionWindow win = new(errorText, stackTrace); + _ = win.ShowDialog(); + } - private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) - { - _logger.Fatal(e); + #endregion - Thread thread = new(ShowUnhandledException) - { - IsBackground = true - }; + #region Events handler - thread.SetApartmentState(ApartmentState.STA); - thread.Start(e.Exception); - thread.Join(); - } + private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) + { + _logger.Fatal(e); - private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) + Thread thread = new(ShowUnhandledException) { - _logger.Fatal(e); + IsBackground = true + }; - object exceptionObject = e.ExceptionObject; + thread.SetApartmentState(ApartmentState.STA); + thread.Start(e.Exception); + thread.Join(); + } - Thread thread = new(ShowUnhandledException) - { - IsBackground = true - }; + private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) + { + _logger.Fatal(e); - thread.SetApartmentState(ApartmentState.STA); - thread.Start(exceptionObject); - thread.Join(); - } + var exceptionObject = e.ExceptionObject; + + Thread thread = new(ShowUnhandledException) + { + IsBackground = true + }; - #endregion + thread.SetApartmentState(ApartmentState.STA); + thread.Start(exceptionObject); + thread.Join(); } + + #endregion } diff --git a/src/Logexpert.Core/Classes/Persister/PersistenceData.cs b/src/Logexpert.Core/Classes/Persister/PersistenceData.cs new file mode 100644 index 00000000..bd358a72 --- /dev/null +++ b/src/Logexpert.Core/Classes/Persister/PersistenceData.cs @@ -0,0 +1,42 @@ +using System.Text; + +using LogExpert.Core.Classes.Filter; +using LogExpert.Core.Entities; + +namespace LogExpert.Core.Classes.Persister; + +public class PersistenceData +{ + #region Fields + + public SortedList bookmarkList = []; + public int bookmarkListPosition = 300; + public bool bookmarkListVisible; + public string columnizerName; + public int currentLine = -1; + public Encoding encoding; + public string fileName; + public bool filterAdvanced; + public List filterParamsList = []; + public int filterPosition = 222; + public bool filterSaveListVisible; + public List filterTabDataList = []; + public bool filterVisible; + public int firstDisplayedLine = -1; + public bool followTail = true; + public string highlightGroupName; + public int lineCount; + + public bool multiFile; + public int multiFileMaxDays; + public List multiFileNames = []; + public string multiFilePattern; + public SortedList rowHeightList = []; + public string sessionFileName; + public bool showBookmarkCommentColumn; + public string tabName; + + public string settingsSaveLoadLocation; + + #endregion +} diff --git a/src/PluginRegistry/FileSystem/LocalFileSystem.cs b/src/PluginRegistry/FileSystem/LocalFileSystem.cs index aafb3eaf..289b1ed3 100644 --- a/src/PluginRegistry/FileSystem/LocalFileSystem.cs +++ b/src/PluginRegistry/FileSystem/LocalFileSystem.cs @@ -1,40 +1,39 @@ -namespace LogExpert.PluginRegistry.FileSystem +namespace LogExpert.PluginRegistry.FileSystem; + +public class LocalFileSystem : IFileSystemPlugin { - public class LocalFileSystem : IFileSystemPlugin - { - #region IFileSystemPlugin Member + #region IFileSystemPlugin Member - public bool CanHandleUri(string uriString) + public bool CanHandleUri(string uriString) + { + try { - try - { - Uri uri = new(uriString); - return uri.IsFile; - } - catch (Exception) - { - return false; - } + Uri uri = new(uriString); + return uri.IsFile; } + catch (Exception) + { + return false; + } + } - public ILogFileInfo GetLogfileInfo(string uriString) + public ILogFileInfo GetLogfileInfo(string uriString) + { + Uri uri = new(uriString); + if (uri.IsFile) { - Uri uri = new(uriString); - if (uri.IsFile) - { - ILogFileInfo logFileInfo = new LogFileInfo(uri); - return logFileInfo; - } - else - { - throw new UriFormatException("Uri " + uriString + " is no file Uri"); - } + ILogFileInfo logFileInfo = new LogFileInfo(uri); + return logFileInfo; + } + else + { + throw new UriFormatException("Uri " + uriString + " is no file Uri"); } + } - public string Text => "Local file system"; + public string Text => "Local file system"; - public string Description => "Access files from normal file system."; + public string Description => "Access files from normal file system."; - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/PluginRegistry/FileSystem/LogFileInfo.cs b/src/PluginRegistry/FileSystem/LogFileInfo.cs index 7c8c4438..31920565 100644 --- a/src/PluginRegistry/FileSystem/LogFileInfo.cs +++ b/src/PluginRegistry/FileSystem/LogFileInfo.cs @@ -1,184 +1,171 @@ using NLog; -namespace LogExpert.PluginRegistry.FileSystem +namespace LogExpert.PluginRegistry.FileSystem; + +public class LogFileInfo : ILogFileInfo { - public class LogFileInfo : ILogFileInfo - { - #region Fields + #region Fields - private const int RETRY_COUNT = 5; - private const int RETRY_SLEEP = 250; - private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); + private const int RETRY_COUNT = 5; + private const int RETRY_SLEEP = 250; + private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); - //FileStream fStream; - private readonly FileInfo fInfo; + //FileStream fStream; + private readonly FileInfo fInfo; - private long lastLength; + private long lastLength; - #endregion + #endregion - #region cTor + #region cTor - public LogFileInfo(Uri fileUri) - { - fInfo = new FileInfo(fileUri.LocalPath); - Uri = fileUri; - OriginalLength = lastLength = LengthWithoutRetry; - //this.oldLength = 0; - } + public LogFileInfo(Uri fileUri) + { + fInfo = new FileInfo(fileUri.LocalPath); + Uri = fileUri; + OriginalLength = lastLength = LengthWithoutRetry; + //this.oldLength = 0; + } - #endregion + #endregion - #region Properties + #region Properties - public string FullName - { - get { return fInfo.FullName; } - } + public string FullName => fInfo.FullName; - public string FileName - { - get { return fInfo.Name; } - } + public string FileName => fInfo.Name; - public string DirectoryName - { - get { return fInfo.DirectoryName; } - } + public string DirectoryName => fInfo.DirectoryName; - public char DirectorySeparatorChar - { - get { return Path.DirectorySeparatorChar; } - } + public char DirectorySeparatorChar => Path.DirectorySeparatorChar; - public Uri Uri { get; } + public Uri Uri { get; } - public long Length + public long Length + { + get { - get + if (fInfo == null) { - if (fInfo == null) - { - return -1; - } + return -1; + } - int retry = RETRY_COUNT; + var retry = RETRY_COUNT; - while (retry > 0) + while (retry > 0) + { + try { - try - { - fInfo.Refresh(); - return fInfo.Length; - } - catch (IOException e) + fInfo.Refresh(); + return fInfo.Length; + } + catch (IOException e) + { + if (--retry <= 0) { - if (--retry <= 0) - { - _logger.Warn(e, "LogFileInfo.Length"); - return -1; - } - Thread.Sleep(RETRY_SLEEP); + _logger.Warn(e, "LogFileInfo.Length"); + return -1; } + Thread.Sleep(RETRY_SLEEP); } - - return -1; } + + return -1; } + } - public long OriginalLength { get; } + public long OriginalLength { get; } - public bool FileExists + public bool FileExists + { + get { - get - { - fInfo.Refresh(); - return fInfo.Exists; - } + fInfo.Refresh(); + return fInfo.Exists; } + } - //TODO this should be set from outside once - public int PollInterval => PluginRegistry.PollingInterval; + //TODO this should be set from outside once + public int PollInterval => PluginRegistry.PollingInterval; - public long LengthWithoutRetry + public long LengthWithoutRetry + { + get { - get + if (fInfo == null) { - if (fInfo == null) - { - return -1; - } - try - { - fInfo.Refresh(); - return fInfo.Length; - } - catch (IOException) - { - return -1; - } + return -1; + } + try + { + fInfo.Refresh(); + return fInfo.Length; + } + catch (IOException) + { + return -1; } } + } - #endregion + #endregion - #region Public methods + #region Public methods - /// - /// Creates a new FileStream for the file. The caller is responsible for closing. - /// If file opening fails it will be tried RETRY_COUNT times. This may be needed sometimes - /// if the file is locked for a short amount of time or temporarly unaccessible because of - /// rollover situations. - /// - /// - public Stream OpenStream() - { - int retry = RETRY_COUNT; + /// + /// Creates a new FileStream for the file. The caller is responsible for closing. + /// If file opening fails it will be tried RETRY_COUNT times. This may be needed sometimes + /// if the file is locked for a short amount of time or temporarly unaccessible because of + /// rollover situations. + /// + /// + public Stream OpenStream() + { + var retry = RETRY_COUNT; - while (true) + while (true) + { + try { - try - { - return new FileStream(fInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); - } - catch (IOException fe) - { - _logger.Debug(fe, "LogFileInfo.OpenFile(): \r\nRetry counter {0}", retry); - if (--retry <= 0) - { - throw; - } - Thread.Sleep(RETRY_SLEEP); - } - catch (UnauthorizedAccessException uae) + return new FileStream(fInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); + } + catch (IOException fe) + { + _logger.Debug(fe, "LogFileInfo.OpenFile(): \r\nRetry counter {0}", retry); + if (--retry <= 0) { - _logger.Debug(uae, "LogFileInfo.OpenFile(): \r\nRetry counter: {0}", retry); - if (--retry <= 0) - { - throw new IOException("Error opening file", uae); - } - Thread.Sleep(RETRY_SLEEP); + throw; } + Thread.Sleep(RETRY_SLEEP); } - } - - //TODO Replace with Event from FileSystemWatcher - public bool FileHasChanged() - { - if (LengthWithoutRetry != lastLength) + catch (UnauthorizedAccessException uae) { - lastLength = LengthWithoutRetry; - return true; + _logger.Debug(uae, "LogFileInfo.OpenFile(): \r\nRetry counter: {0}", retry); + if (--retry <= 0) + { + throw new IOException("Error opening file", uae); + } + Thread.Sleep(RETRY_SLEEP); } - return false; } + } - public override string ToString() + //TODO Replace with Event from FileSystemWatcher + public bool FileHasChanged() + { + if (LengthWithoutRetry != lastLength) { - return fInfo.FullName + ", OldLen: " + OriginalLength + ", Len: " + Length; + lastLength = LengthWithoutRetry; + return true; } + return false; + } - #endregion + public override string ToString() + { + return fInfo.FullName + ", OldLen: " + OriginalLength + ", Len: " + Length; } + + #endregion } \ No newline at end of file diff --git a/src/PluginRegistry/PluginRegistry.cs b/src/PluginRegistry/PluginRegistry.cs index 0ba17139..24547ff6 100644 --- a/src/PluginRegistry/PluginRegistry.cs +++ b/src/PluginRegistry/PluginRegistry.cs @@ -1,386 +1,386 @@ -using LogExpert.Core.Classes; +using System.Reflection; + +using LogExpert.Core.Classes; using LogExpert.Core.Classes.Columnizer; using LogExpert.Core.Entities; using LogExpert.Core.Interface; using LogExpert.PluginRegistry.FileSystem; + using NLog; -using System.Reflection; -namespace LogExpert.PluginRegistry +namespace LogExpert.PluginRegistry; + +/// +/// Holds all registered plugins. +/// +/// +/// It all has started with Columnizers only. So the different types of plugins have no common super interface. I didn't change it +/// to keep existing plugin API stable. In a future version this may change. +/// +public class PluginRegistry : IPluginRegistry { - /// - /// Holds all registered plugins. - /// - /// - /// It all has started with Columnizers only. So the different types of plugins have no common super interface. I didn't change it - /// to keep existing plugin API stable. In a future version this may change. - /// - public class PluginRegistry : IPluginRegistry - { - #region Fields + #region Fields + + private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); + private static PluginRegistry? _instance; + private static readonly object _lock = new(); - private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); - private static PluginRegistry? _instance; - private static readonly object _lock = new(); + private readonly IFileSystemCallback _fileSystemCallback = new FileSystemCallback(); + private readonly IList _pluginList = []; + private readonly IDictionary _registeredKeywordsDict = new Dictionary(); - private readonly IFileSystemCallback _fileSystemCallback = new FileSystemCallback(); - private readonly IList _pluginList = []; - private readonly IDictionary _registeredKeywordsDict = new Dictionary(); + #endregion - #endregion + private static string _applicationConfigurationFolder = string.Empty; + private static int _pollingInterval = 250; - private static string _applicationConfigurationFolder = string.Empty; - private static int _pollingInterval = 250; + #region cTor + // Private constructor to prevent instantiation + private PluginRegistry (string applicationConfigurationFolder, int pollingInterval) + { + _applicationConfigurationFolder = applicationConfigurationFolder; + _pollingInterval = pollingInterval; + } - #region cTor - // Private constructor to prevent instantiation - private PluginRegistry(string applicationConfigurationFolder, int pollingInterval) + public PluginRegistry Create (string applicationConfigurationFolder, int pollingInterval) + { + if (_instance != null) { - _applicationConfigurationFolder = applicationConfigurationFolder; - _pollingInterval = pollingInterval; + return _instance; } - public PluginRegistry Create(string applicationConfigurationFolder, int pollingInterval) + lock (_lock) { - if (_instance != null) - { - return _instance; - } + _instance = new PluginRegistry(applicationConfigurationFolder, pollingInterval); + } - lock (_lock) - { - _instance ??= new PluginRegistry(applicationConfigurationFolder, pollingInterval); - } + _applicationConfigurationFolder = applicationConfigurationFolder; + _pollingInterval = pollingInterval; - _applicationConfigurationFolder = applicationConfigurationFolder; - _pollingInterval = pollingInterval; + _instance.LoadPlugins(); + return Instance; + } - _instance.LoadPlugins(); - return Instance; - } + #endregion - #endregion + #region Properties - #region Properties + public static PluginRegistry Instance => _instance ?? new PluginRegistry(_applicationConfigurationFolder, _pollingInterval); - public static PluginRegistry Instance => _instance ?? new PluginRegistry(_applicationConfigurationFolder, _pollingInterval); + public IList RegisteredColumnizers { get; private set; } - public IList RegisteredColumnizers { get; private set; } + public IList RegisteredContextMenuPlugins { get; } = []; - public IList RegisteredContextMenuPlugins { get; } = []; + public IList RegisteredKeywordActions { get; } = []; - public IList RegisteredKeywordActions { get; } = []; + public IList RegisteredFileSystemPlugins { get; } = []; - public IList RegisteredFileSystemPlugins { get; } = []; + #endregion - #endregion + #region Public methods - #region Public methods + public static int PollingInterval => _pollingInterval; - public static int PollingInterval => _pollingInterval; + #endregion - #endregion + #region Internals - #region Internals + internal void LoadPlugins () + { + _logger.Info("Loading plugins..."); + + RegisteredColumnizers = + [ + //TODO: Remove these plugins and load them as any other plugin + new DefaultLogfileColumnizer(), + new TimestampColumnizer(), + new SquareBracketColumnizer(), + new ClfColumnizer(), + ]; + RegisteredFileSystemPlugins.Add(new LocalFileSystem()); + + var pluginDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "plugins"); + //TODO: FIXME: This is a hack for the tests to pass. Need to find a better approach + if (!Directory.Exists(pluginDir)) + { + pluginDir = "."; + } + + AppDomain.CurrentDomain.AssemblyResolve += ColumnizerResolveEventHandler; - internal void LoadPlugins() + var interfaceName = typeof(ILogLineColumnizer).FullName + ?? throw new NotImplementedException("The interface name is null. How did this happen? Let's fix this."); + + foreach (var dllName in Directory.EnumerateFiles(pluginDir, "*.dll")) { - _logger.Info("Loading plugins..."); - - RegisteredColumnizers = - [ - //TODO: Remove these plugins and load them as any other plugin - new DefaultLogfileColumnizer(), - new TimestampColumnizer(), - new SquareBracketColumnizer(), - new ClfColumnizer(), - ]; - RegisteredFileSystemPlugins.Add(new LocalFileSystem()); - - string pluginDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "plugins"); - //TODO: FIXME: This is a hack for the tests to pass. Need to find a better approach - if (!Directory.Exists(pluginDir)) + try { - pluginDir = "."; + LoadPluginAssembly(dllName, interfaceName); } - - AppDomain.CurrentDomain.AssemblyResolve += ColumnizerResolveEventHandler; - - var interfaceName = typeof(ILogLineColumnizer).FullName; - if (interfaceName == null) { - throw new NotImplementedException("The interface name is null. How did this happen? Let's fix this."); + catch (Exception ex) when (ex is BadImageFormatException or FileLoadException) + { + // Can happen when a 32bit-only DLL is loaded on a 64bit system (or vice versa) + // or could be a not columnizer DLL (e.g. A DLL that is needed by a plugin). + _logger.Error(ex, dllName); } - foreach (string dllName in Directory.EnumerateFiles(pluginDir, "*.dll")) + catch (ReflectionTypeLoadException ex) { - try + // can happen when a dll dependency is missing + if (ex.LoaderExceptions != null && ex.LoaderExceptions.Length != 0) { - LoadPluginAssembly(dllName, interfaceName); - } - catch (Exception ex) when (ex is BadImageFormatException or FileLoadException) - { - // Can happen when a 32bit-only DLL is loaded on a 64bit system (or vice versa) - // or could be a not columnizer DLL (e.g. A DLL that is needed by a plugin). - _logger.Error(ex, dllName); - } - catch (ReflectionTypeLoadException ex) - { - // can happen when a dll dependency is missing - if (ex.LoaderExceptions != null && ex.LoaderExceptions.Length != 0) + foreach (Exception loaderException in ex.LoaderExceptions) { - foreach (Exception loaderException in ex.LoaderExceptions) - { - _logger.Error(loaderException, "Plugin load failed with '{0}'", dllName); - } + _logger.Error(loaderException, "Plugin load failed with '{0}'", dllName); } - _logger.Error(ex, "Loader exception during load of dll '{0}'", dllName); - throw; - } - catch (Exception ex) - { - _logger.Error(ex, $"General Exception for the file {dllName}, of type: {ex.GetType()}, with the message: {ex.Message}"); - throw; } + _logger.Error(ex, "Loader exception during load of dll '{0}'", dllName); + throw; + } + catch (Exception ex) + { + _logger.Error(ex, $"General Exception for the file {dllName}, of type: {ex.GetType()}, with the message: {ex.Message}"); + throw; } - - _logger.Info("Plugin loading complete."); } - private void LoadPluginAssembly(string dllName, string interfaceName) + _logger.Info("Plugin loading complete."); + } + + private void LoadPluginAssembly (string dllName, string interfaceName) + { + var assembly = Assembly.LoadFrom(dllName); + Type[] types = assembly.GetTypes(); + + foreach (Type type in types) { - Assembly assembly = Assembly.LoadFrom(dllName); - var types = assembly.GetTypes(); + _logger.Info($"Type {type.FullName} in assembly {assembly.FullName} implements {interfaceName}"); - foreach (var type in types) + if (type.GetInterfaces().Any(i => i.FullName == interfaceName)) { - _logger.Info($"Type {type.FullName} in assembly {assembly.FullName} implements {interfaceName}"); - - if (type.GetInterfaces().Any(i => i.FullName == interfaceName)) + ConstructorInfo cti = type.GetConstructor(Type.EmptyTypes); + if (cti != null) { - ConstructorInfo cti = type.GetConstructor(Type.EmptyTypes); - if (cti != null) - { - object instance = cti.Invoke([]); - RegisteredColumnizers.Add((ILogLineColumnizer)instance); - - if (instance is IColumnizerConfigurator configurator) - { - configurator.LoadConfig(_applicationConfigurationFolder); - } + var instance = cti.Invoke([]); + RegisteredColumnizers.Add((ILogLineColumnizer)instance); - if (instance is ILogExpertPlugin plugin) - { - _pluginList.Add(plugin); - plugin.PluginLoaded(); - } - - _logger.Info("Added columnizer {0}", type.Name); - } - } - else - { - if (TryAsContextMenu(type)) + if (instance is IColumnizerConfigurator configurator) { - continue; + configurator.LoadConfig(_applicationConfigurationFolder); } - if (TryAsKeywordAction(type)) + if (instance is ILogExpertPlugin plugin) { - continue; + _pluginList.Add(plugin); + plugin.PluginLoaded(); } - if (TryAsFileSystem(type)) - { - continue; - } + _logger.Info($"Added columnizer {type.Name}"); + } + } + else + { + if (TryAsContextMenu(type)) + { + continue; + } + + if (TryAsKeywordAction(type)) + { + continue; + } + + if (TryAsFileSystem(type)) + { + continue; } } } + } + + public IKeywordAction FindKeywordActionPluginByName (string name) + { + _registeredKeywordsDict.TryGetValue(name, out IKeywordAction action); + return action; + } - public IKeywordAction FindKeywordActionPluginByName(string name) + public void CleanupPlugins () + { + foreach (ILogExpertPlugin plugin in _pluginList) { - _registeredKeywordsDict.TryGetValue(name, out IKeywordAction action); - return action; + plugin.AppExiting(); } + } - public void CleanupPlugins() + public IFileSystemPlugin FindFileSystemForUri (string uriString) + { + if (_logger.IsDebugEnabled) { - foreach (ILogExpertPlugin plugin in _pluginList) - { - plugin.AppExiting(); - } + _logger.Debug("Trying to find file system plugin for uri {0}", uriString); } - public IFileSystemPlugin FindFileSystemForUri(string uriString) + foreach (IFileSystemPlugin fs in RegisteredFileSystemPlugins) { if (_logger.IsDebugEnabled) { - _logger.Debug("Trying to find file system plugin for uri {0}", uriString); + _logger.Debug("Checking {0}", fs.Text); } - foreach (IFileSystemPlugin fs in RegisteredFileSystemPlugins) + if (fs.CanHandleUri(uriString)) { if (_logger.IsDebugEnabled) { - _logger.Debug("Checking {0}", fs.Text); + _logger.Debug("Found match {0}", fs.Text); } - if (fs.CanHandleUri(uriString)) - { - if (_logger.IsDebugEnabled) - { - _logger.Debug("Found match {0}", fs.Text); - } - - return fs; - } + return fs; } - - _logger.Error("No file system plugin found for uri {0}", uriString); - return null; } - #endregion + _logger.Error("No file system plugin found for uri {0}", uriString); + return null; + } - #region Private Methods - //TODO: Can this be delted? - private bool TryAsContextMenu(Type type) - { - IContextMenuEntry me = TryInstantiate(type); + #endregion - if (me != null) - { - RegisteredContextMenuPlugins.Add(me); - if (me is ILogExpertPluginConfigurator configurator) - { - configurator.LoadConfig(_applicationConfigurationFolder); - } + #region Private Methods + //TODO: Can this be deleted? + private bool TryAsContextMenu (Type type) + { + IContextMenuEntry me = TryInstantiate(type); - if (me is ILogExpertPlugin plugin) - { - _pluginList.Add(plugin); - plugin.PluginLoaded(); - } + if (me != null) + { + RegisteredContextMenuPlugins.Add(me); + if (me is ILogExpertPluginConfigurator configurator) + { + configurator.LoadConfig(_applicationConfigurationFolder); + } - _logger.Info("Added context menu plugin {0}", type); - return true; + if (me is ILogExpertPlugin plugin) + { + _pluginList.Add(plugin); + plugin.PluginLoaded(); } - return false; + _logger.Info("Added context menu plugin {0}", type); + return true; } - //TODO: Can this be delted? - private bool TryAsKeywordAction(Type type) + return false; + } + + //TODO: Can this be delted? + private bool TryAsKeywordAction (Type type) + { + IKeywordAction ka = TryInstantiate(type); + if (ka != null) { - IKeywordAction ka = TryInstantiate(type); - if (ka != null) + RegisteredKeywordActions.Add(ka); + _registeredKeywordsDict.Add(ka.GetName(), ka); + if (ka is ILogExpertPluginConfigurator configurator) { - RegisteredKeywordActions.Add(ka); - _registeredKeywordsDict.Add(ka.GetName(), ka); - if (ka is ILogExpertPluginConfigurator configurator) - { - configurator.LoadConfig(_applicationConfigurationFolder); - } - - if (ka is ILogExpertPlugin plugin) - { - _pluginList.Add(plugin); - plugin.PluginLoaded(); - } + configurator.LoadConfig(_applicationConfigurationFolder); + } - _logger.Info("Added keyword plugin {0}", type); - return true; + if (ka is ILogExpertPlugin plugin) + { + _pluginList.Add(plugin); + plugin.PluginLoaded(); } - return false; + _logger.Info("Added keyword plugin {0}", type); + return true; } - //TODO: Can this be delted? - private bool TryAsFileSystem(Type type) - { - // file system plugins can have optional constructor with IFileSystemCallback argument - IFileSystemPlugin fs = TryInstantiate(type, _fileSystemCallback); - fs ??= TryInstantiate(type); + return false; + } - if (fs != null) - { - RegisteredFileSystemPlugins.Add(fs); - if (fs is ILogExpertPluginConfigurator configurator) - { - //TODO Refactor, this should be set from outside once and not loaded all the time - configurator.LoadConfig(_applicationConfigurationFolder); - } + //TODO: Can this be delted? + private bool TryAsFileSystem (Type type) + { + // file system plugins can have optional constructor with IFileSystemCallback argument + IFileSystemPlugin fs = TryInstantiate(type, _fileSystemCallback); + fs ??= TryInstantiate(type); - if (fs is ILogExpertPlugin plugin) - { - _pluginList.Add(plugin); - plugin.PluginLoaded(); - } + if (fs != null) + { + RegisteredFileSystemPlugins.Add(fs); + if (fs is ILogExpertPluginConfigurator configurator) + { + //TODO Refactor, this should be set from outside once and not loaded all the time + configurator.LoadConfig(_applicationConfigurationFolder); + } - _logger.Info("Added file system plugin {0}", type); - return true; + if (fs is ILogExpertPlugin plugin) + { + _pluginList.Add(plugin); + plugin.PluginLoaded(); } - return false; + _logger.Info("Added file system plugin {0}", type); + return true; } - private static T TryInstantiate(Type loadedType) where T : class + return false; + } + + private static T TryInstantiate (Type loadedType) where T : class + { + Type t = typeof(T); + Type inter = loadedType.GetInterface(t.Name); + if (inter != null) { - Type t = typeof(T); - Type inter = loadedType.GetInterface(t.Name); - if (inter != null) + ConstructorInfo cti = loadedType.GetConstructor(Type.EmptyTypes); + if (cti != null) { - ConstructorInfo cti = loadedType.GetConstructor(Type.EmptyTypes); - if (cti != null) - { - object o = cti.Invoke([]); - return o as T; - } + var o = cti.Invoke([]); + return o as T; } - - return default; } - private static T TryInstantiate(Type loadedType, IFileSystemCallback fsCallback) where T : class + return default; + } + + private static T TryInstantiate (Type loadedType, IFileSystemCallback fsCallback) where T : class + { + Type t = typeof(T); + Type inter = loadedType.GetInterface(t.Name); + if (inter != null) { - Type t = typeof(T); - Type inter = loadedType.GetInterface(t.Name); - if (inter != null) + ConstructorInfo cti = loadedType.GetConstructor([typeof(IFileSystemCallback)]); + if (cti != null) { - ConstructorInfo cti = loadedType.GetConstructor([typeof(IFileSystemCallback)]); - if (cti != null) - { - object o = cti.Invoke([fsCallback]); - return o as T; - } + var o = cti.Invoke([fsCallback]); + return o as T; } - - return default; } - #endregion + return default; + } - #region Events handler + #endregion - private static Assembly ColumnizerResolveEventHandler(object? sender, ResolveEventArgs args) - { - string fileName = new AssemblyName(args.Name).Name + ".dll"; + #region Events handler - string mainDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName); - string pluginDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "plugins", fileName); + private static Assembly ColumnizerResolveEventHandler (object? sender, ResolveEventArgs args) + { + var fileName = new AssemblyName(args.Name).Name + ".dll"; - if (File.Exists(mainDir)) - { - return Assembly.LoadFrom(mainDir); - } + var mainDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName); + var pluginDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "plugins", fileName); - if (File.Exists(pluginDir)) - { - return Assembly.LoadFrom(pluginDir); - } + if (File.Exists(mainDir)) + { + return Assembly.LoadFrom(mainDir); + } - return null; + if (File.Exists(pluginDir)) + { + return Assembly.LoadFrom(pluginDir); } - #endregion + return null; } + + #endregion } \ No newline at end of file diff --git a/src/RegexColumnizer.UnitTests/RegexColumnizerTests.cs b/src/RegexColumnizer.UnitTests/RegexColumnizerTests.cs index 6728420d..54312b0e 100644 --- a/src/RegexColumnizer.UnitTests/RegexColumnizerTests.cs +++ b/src/RegexColumnizer.UnitTests/RegexColumnizerTests.cs @@ -4,69 +4,66 @@ using System.Runtime.Versioning; [assembly: SupportedOSPlatform("windows")] -namespace RegexColumnizer.UnitTests +namespace RegexColumnizer.UnitTests; + +[TestFixture] +public class RegexColumnizerTests { - [TestFixture] - public class RegexColumnizerTests + // The same amount of columns should be returned whether the line matches the regex or not. + [TestCase("5 test message", @"^(?'time'[\d]+)\s+(?'Message'.+)$", 2)] + [TestCase("Error in com.example.core", @"^(?'time'[\d]+)\s+(?'Message'.+)$", 2)] + public void SplitLine_ColumnCountMatches(string lineToParse, string regex, int expectedNumberOfColumns) { - // The same amount of columns should be returned whether the line matches the regex or not. - [TestCase("5 test message", @"^(?'time'[\d]+)\s+(?'Message'.+)$", 2)] - [TestCase("Error in com.example.core", @"^(?'time'[\d]+)\s+(?'Message'.+)$", 2)] - public void SplitLine_ColumnCountMatches(string lineToParse, string regex, int expectedNumberOfColumns) - { - Regex1Columnizer columnizer = CreateInitializedColumnizer(regex); + Regex1Columnizer columnizer = CreateInitializedColumnizer(regex); - TestLogLine testLogLine = new(4, lineToParse); - IColumnizedLogLine parsedLogLine = columnizer.SplitLine(Mock.Of(), testLogLine); + TestLogLine testLogLine = new(4, lineToParse); + IColumnizedLogLine parsedLogLine = columnizer.SplitLine(Mock.Of(), testLogLine); - Assert.That(expectedNumberOfColumns, Is.EqualTo(parsedLogLine.ColumnValues.Length)); - } + Assert.That(expectedNumberOfColumns, Is.EqualTo(parsedLogLine.ColumnValues.Length)); + } - //Using "" for empty string since string.Empty can't be passed to the TestCase attribute. - [TestCase("5 test message", @"^(?'time'[\d]+)\s+(?'Message'.+)$", 0, "5")] - [TestCase("5 test message", @"^(?'time'[\d]+)\s+(?'Message'.+)$", 1, "test message")] - [TestCase("Error in com.example.core", @"^(?'time'[\d]+)\s+(?'Message'.+)$", 0, "")] // doesn't match regex so should be empty - [TestCase("Error in com.example.core", @"^(?'time'[\d]+)\s+(?'Message'.+)$", 1, "Error in com.example.core")] - public void SplitLine_ColumnValues(string lineToParse, string regex, int columnIndexToTest, - string expectedColumnValue) - { - Regex1Columnizer columnizer = CreateInitializedColumnizer(regex); + //Using "" for empty string since string.Empty can't be passed to the TestCase attribute. + [TestCase("5 test message", @"^(?'time'[\d]+)\s+(?'Message'.+)$", 0, "5")] + [TestCase("5 test message", @"^(?'time'[\d]+)\s+(?'Message'.+)$", 1, "test message")] + [TestCase("Error in com.example.core", @"^(?'time'[\d]+)\s+(?'Message'.+)$", 0, "")] // doesn't match regex so should be empty + [TestCase("Error in com.example.core", @"^(?'time'[\d]+)\s+(?'Message'.+)$", 1, "Error in com.example.core")] + public void SplitLine_ColumnValues(string lineToParse, string regex, int columnIndexToTest, + string expectedColumnValue) + { + Regex1Columnizer columnizer = CreateInitializedColumnizer(regex); - TestLogLine testLogLine = new(3, lineToParse); - IColumnizedLogLine parsedLogLine = columnizer.SplitLine(Mock.Of(), testLogLine); + TestLogLine testLogLine = new(3, lineToParse); + IColumnizedLogLine parsedLogLine = columnizer.SplitLine(Mock.Of(), testLogLine); - Assert.That(expectedColumnValue, Is.EqualTo(parsedLogLine.ColumnValues[columnIndexToTest].Text)); - } + Assert.That(expectedColumnValue, Is.EqualTo(parsedLogLine.ColumnValues[columnIndexToTest].Text)); + } - private Regex1Columnizer CreateInitializedColumnizer(string regex) + private Regex1Columnizer CreateInitializedColumnizer(string regex) + { + RegexColumnizerConfig columnizerConfig = new() { - RegexColumnizerConfig columnizerConfig = new() - { - Expression = regex, - Name = "Test regex" - }; + Expression = regex, + Name = "Test regex" + }; - Regex1Columnizer columnizer = new(); - //TODO this should be an internal function - columnizer.Init(columnizerConfig); - return columnizer; - } + Regex1Columnizer columnizer = new(); + //TODO this should be an internal function + columnizer.Init(columnizerConfig); + return columnizer; + } - private class TestLogLine : ILogLine + private class TestLogLine : ILogLine + { + public TestLogLine(int lineNumber, string fullLine) { - public TestLogLine(int lineNumber, string fullLine) - { - LineNumber = lineNumber; - FullLine = fullLine; - } + LineNumber = lineNumber; + FullLine = fullLine; + } - public string FullLine { get; set; } + public string FullLine { get; set; } - public int LineNumber { get; set; } + public int LineNumber { get; set; } - public string Text { get; set; } - } + public string Text { get; set; } } - - } diff --git a/src/RegexColumnizer/RegexColumnizer.cs b/src/RegexColumnizer/RegexColumnizer.cs index 89143937..bc66b146 100644 --- a/src/RegexColumnizer/RegexColumnizer.cs +++ b/src/RegexColumnizer/RegexColumnizer.cs @@ -8,241 +8,240 @@ using System.Xml.Serialization; [assembly: SupportedOSPlatform("windows")] -namespace RegexColumnizer +namespace RegexColumnizer; + +public abstract class BaseRegexColumnizer : ILogLineColumnizer, IColumnizerConfigurator { - public abstract class BaseRegexColumnizer : ILogLineColumnizer, IColumnizerConfigurator - { - #region Fields + #region Fields - private readonly XmlSerializer xml = new XmlSerializer(typeof(RegexColumnizerConfig)); - private string[] columns; + private readonly XmlSerializer xml = new XmlSerializer(typeof(RegexColumnizerConfig)); + private string[] columns; - #endregion + #endregion - #region Properties + #region Properties - public RegexColumnizerConfig Config { get; private set; } - - public Regex Regex { get; private set; } + public RegexColumnizerConfig Config { get; private set; } + + public Regex Regex { get; private set; } - #endregion + #endregion - #region Public methods + #region Public methods - public string GetName() + public string GetName() + { + if (Config == null || string.IsNullOrWhiteSpace(Config.Name)) { - if (Config == null || string.IsNullOrWhiteSpace(Config.Name)) - { - return GetNameInternal(); - } - - return Config.Name; + return GetNameInternal(); } - public string GetDescription() => "Columns are filled by regular expression named capture groups"; - - public int GetColumnCount() => columns.Length; - public string[] GetColumnNames() => columns; + return Config.Name; + } + public string GetDescription() => "Columns are filled by regular expression named capture groups"; + + public int GetColumnCount() => columns.Length; - public IColumnizedLogLine SplitLine(ILogLineColumnizerCallback callback, ILogLine line) + public string[] GetColumnNames() => columns; + + public IColumnizedLogLine SplitLine(ILogLineColumnizerCallback callback, ILogLine line) + { + var logLine = new ColumnizedLogLine(); + + logLine.ColumnValues = new IColumn[columns.Length]; + if (Regex != null) { - ColumnizedLogLine logLine = new ColumnizedLogLine(); + var m = Regex.Match(line.FullLine); - logLine.ColumnValues = new IColumn[columns.Length]; - if (Regex != null) + if (m.Success) { - var m = Regex.Match(line.FullLine); - - if (m.Success) - { - for (int i = m.Groups.Count - 1; i > 0; i--) - { - logLine.ColumnValues[i - 1] = new Column - { - Parent = logLine, - FullValue = m.Groups[i].Value - }; - } - } - else + for (var i = m.Groups.Count - 1; i > 0; i--) { - //Move non matching lines in the last column - logLine.ColumnValues[columns.Length - 1] = new Column + logLine.ColumnValues[i - 1] = new Column { Parent = logLine, - FullValue = line.FullLine + FullValue = m.Groups[i].Value }; - - - //Fill other columns with empty string to avoid null pointer exceptions in unexpected places - for (var i = 0; i < columns.Length - 1; i++) - { - logLine.ColumnValues[i] = new Column - { - Parent = logLine, - FullValue = string.Empty - }; - } } } else { - IColumn colVal = new Column + //Move non matching lines in the last column + logLine.ColumnValues[columns.Length - 1] = new Column { Parent = logLine, FullValue = line.FullLine }; - logLine.ColumnValues[0] = colVal; + + //Fill other columns with empty string to avoid null pointer exceptions in unexpected places + for (var i = 0; i < columns.Length - 1; i++) + { + logLine.ColumnValues[i] = new Column + { + Parent = logLine, + FullValue = string.Empty + }; + } } - - logLine.LogLine = line; - return logLine; } - - public bool IsTimeshiftImplemented() => false; - - public void SetTimeOffset(int msecOffset) + else { - throw new NotImplementedException(); - } + IColumn colVal = new Column + { + Parent = logLine, + FullValue = line.FullLine + }; - public int GetTimeOffset() - { - throw new NotImplementedException(); + logLine.ColumnValues[0] = colVal; } - public DateTime GetTimestamp(ILogLineColumnizerCallback callback, ILogLine line) - { - throw new NotImplementedException(); - } + logLine.LogLine = line; + return logLine; + } - public void PushValue(ILogLineColumnizerCallback callback, int column, string value, string oldValue) - { - throw new NotImplementedException(); - } + public bool IsTimeshiftImplemented() => false; - public void Configure(ILogLineColumnizerCallback callback, string configDir) - { - RegexColumnizerConfigDialog dialog = new RegexColumnizerConfigDialog {Config = Config}; - if (dialog.ShowDialog() == DialogResult.OK) - { - var configFile = GetConfigFile(configDir); - using (var w = new FileStream(configFile, FileMode.Create)) - { - xml.Serialize(w, dialog.Config); - } + public void SetTimeOffset(int msecOffset) + { + throw new NotImplementedException(); + } - Init(dialog.Config); - } - } + public int GetTimeOffset() + { + throw new NotImplementedException(); + } + + public DateTime GetTimestamp(ILogLineColumnizerCallback callback, ILogLine line) + { + throw new NotImplementedException(); + } - public void LoadConfig(string configDir) + public void PushValue(ILogLineColumnizerCallback callback, int column, string value, string oldValue) + { + throw new NotImplementedException(); + } + + public void Configure(ILogLineColumnizerCallback callback, string configDir) + { + var dialog = new RegexColumnizerConfigDialog {Config = Config}; + if (dialog.ShowDialog() == DialogResult.OK) { var configFile = GetConfigFile(configDir); - RegexColumnizerConfig config; - if (!File.Exists(configFile)) - { - config = new RegexColumnizerConfig - { - Name = GetName() - }; - } - else + using (var w = new FileStream(configFile, FileMode.Create)) { - using (var reader = new StreamReader(configFile)) - { - config = xml.Deserialize(reader) as RegexColumnizerConfig; - } + xml.Serialize(w, dialog.Config); } - Init(config); + Init(dialog.Config); } + } - public string GetConfigFile(string configDir) - { - var name = GetType().Name; - string configPath = Path.Combine(configDir, name); - configPath = Path.ChangeExtension(configPath, "xml"); //todo change to json - return configPath; - } - - #endregion - - /// - /// ToString, this is displayed in the columnizer picker combobox only in the FilterSelectionDialog - /// - /// - public override string ToString() + public void LoadConfig(string configDir) + { + var configFile = GetConfigFile(configDir); + RegexColumnizerConfig config; + if (!File.Exists(configFile)) { - return GetName(); + config = new RegexColumnizerConfig + { + Name = GetName() + }; } - - #region Private Methods - - protected abstract string GetNameInternal(); - - public void Init(RegexColumnizerConfig config) + else { - Config = config; - - try + using (var reader = new StreamReader(configFile)) { - Regex = new Regex(Config.Expression, RegexOptions.Compiled); - int skip = Regex.GetGroupNames().Length == 1 ? 0 : 1; - columns = Regex.GetGroupNames().Skip(skip).ToArray(); - } - catch - { - Regex = null; + config = xml.Deserialize(reader) as RegexColumnizerConfig; } } - #endregion + Init(config); } - public class Regex1Columnizer : BaseRegexColumnizer + public string GetConfigFile(string configDir) { - protected override string GetNameInternal() => "Regex1"; + var name = GetType().Name; + var configPath = Path.Combine(configDir, name); + configPath = Path.ChangeExtension(configPath, "xml"); //todo change to json + return configPath; } - public class Regex2Columnizer : BaseRegexColumnizer - { - protected override string GetNameInternal() => "Regex2"; - } + #endregion - public class Regex3Columnizer : BaseRegexColumnizer + /// + /// ToString, this is displayed in the columnizer picker combobox only in the FilterSelectionDialog + /// + /// + public override string ToString() { - protected override string GetNameInternal() => "Regex3"; + return GetName(); } - public class Regex4Columnizer : BaseRegexColumnizer - { - protected override string GetNameInternal() => "Regex4"; - } + #region Private Methods - public class Regex5Columnizer : BaseRegexColumnizer - { - protected override string GetNameInternal() => "Regex5"; - } + protected abstract string GetNameInternal(); - public class Regex6Columnizer : BaseRegexColumnizer + public void Init(RegexColumnizerConfig config) { - protected override string GetNameInternal() => "Regex6"; - } + Config = config; - public class Regex7Columnizer : BaseRegexColumnizer - { - protected override string GetNameInternal() => "Regex7"; + try + { + Regex = new Regex(Config.Expression, RegexOptions.Compiled); + var skip = Regex.GetGroupNames().Length == 1 ? 0 : 1; + columns = Regex.GetGroupNames().Skip(skip).ToArray(); + } + catch + { + Regex = null; + } } - public class Regex8Columnizer : BaseRegexColumnizer - { - protected override string GetNameInternal() => "Regex8"; - } + #endregion +} - public class Regex9Columnizer : BaseRegexColumnizer - { - protected override string GetNameInternal() => "Regex9"; - } +public class Regex1Columnizer : BaseRegexColumnizer +{ + protected override string GetNameInternal() => "Regex1"; +} + +public class Regex2Columnizer : BaseRegexColumnizer +{ + protected override string GetNameInternal() => "Regex2"; +} + +public class Regex3Columnizer : BaseRegexColumnizer +{ + protected override string GetNameInternal() => "Regex3"; +} + +public class Regex4Columnizer : BaseRegexColumnizer +{ + protected override string GetNameInternal() => "Regex4"; +} + +public class Regex5Columnizer : BaseRegexColumnizer +{ + protected override string GetNameInternal() => "Regex5"; +} + +public class Regex6Columnizer : BaseRegexColumnizer +{ + protected override string GetNameInternal() => "Regex6"; +} + +public class Regex7Columnizer : BaseRegexColumnizer +{ + protected override string GetNameInternal() => "Regex7"; +} + +public class Regex8Columnizer : BaseRegexColumnizer +{ + protected override string GetNameInternal() => "Regex8"; +} + +public class Regex9Columnizer : BaseRegexColumnizer +{ + protected override string GetNameInternal() => "Regex9"; } \ No newline at end of file diff --git a/src/RegexColumnizer/RegexColumnizerConfig.cs b/src/RegexColumnizer/RegexColumnizerConfig.cs index f9b3897b..a8547403 100644 --- a/src/RegexColumnizer/RegexColumnizerConfig.cs +++ b/src/RegexColumnizer/RegexColumnizerConfig.cs @@ -1,13 +1,12 @@ -namespace RegexColumnizer +namespace RegexColumnizer; + +public class RegexColumnizerConfig { - public class RegexColumnizerConfig - { - #region Properties + #region Properties - public string Expression { get; set; } = "(?.*)"; + public string Expression { get; set; } = "(?.*)"; - public string Name { get; set; } + public string Name { get; set; } - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/RegexColumnizer/RegexColumnizerConfigDialog.cs b/src/RegexColumnizer/RegexColumnizerConfigDialog.cs index b44cf02f..a355aa38 100644 --- a/src/RegexColumnizer/RegexColumnizerConfigDialog.cs +++ b/src/RegexColumnizer/RegexColumnizerConfigDialog.cs @@ -5,78 +5,77 @@ using System.Text.RegularExpressions; using System.Windows.Forms; -namespace RegexColumnizer +namespace RegexColumnizer; + +public partial class RegexColumnizerConfigDialog : Form { - public partial class RegexColumnizerConfigDialog : Form + public RegexColumnizerConfigDialog() { - public RegexColumnizerConfigDialog() - { - SuspendLayout(); - AutoScaleDimensions = new SizeF(96F, 96F); - AutoScaleMode = AutoScaleMode.Dpi; - - InitializeComponent(); - ResumeLayout(); - } + SuspendLayout(); + AutoScaleDimensions = new SizeF(96F, 96F); + AutoScaleMode = AutoScaleMode.Dpi; - public RegexColumnizerConfig Config { get; set; } - - private void OnBtnOkClick(object sender, EventArgs e) - { - if (Check()) - { - Config.Expression = tbExpression.Text; - Config.Name = tbName.Text; - } + InitializeComponent(); + ResumeLayout(); + } - } + public RegexColumnizerConfig Config { get; set; } - private void RegexColumnizerConfigDialog_Load(object sender, EventArgs e) + private void OnBtnOkClick(object sender, EventArgs e) + { + if (Check()) { - tbExpression.Text = Config.Expression; - tbName.Text = Config.Name; + Config.Expression = tbExpression.Text; + Config.Name = tbName.Text; } - private void OnButtonCheckClick(object sender, EventArgs e) - { - Check(); - } + } - private bool Check() - { - DataTable table = new(); + private void RegexColumnizerConfigDialog_Load(object sender, EventArgs e) + { + tbExpression.Text = Config.Expression; + tbName.Text = Config.Name; + } - try - { - Regex regex = new(tbExpression.Text); - var groupNames = regex.GetGroupNames(); - int offset = groupNames.Length > 1 ? 1 : 0; + private void OnButtonCheckClick(object sender, EventArgs e) + { + Check(); + } - for (int i = offset; i < groupNames.Length; i++) - { - table.Columns.Add(groupNames[i]); - } + private bool Check() + { + DataTable table = new(); - if (!string.IsNullOrEmpty(tbTestLine.Text)) - { - Match match = regex.Match(tbTestLine.Text); - var row = table.NewRow(); - var values = match.Groups.OfType().Skip(offset).Select(group => group.Value).Cast().ToArray(); - row.ItemArray = values; - table.Rows.Add(row); - } + try + { + Regex regex = new(tbExpression.Text); + var groupNames = regex.GetGroupNames(); + var offset = groupNames.Length > 1 ? 1 : 0; - return true; - } - catch (Exception ex) + for (var i = offset; i < groupNames.Length; i++) { - MessageBox.Show($@"Invalid Regex !{Environment.NewLine}{ex.Message}", @"Regex Columnizer Configuration", MessageBoxButtons.OK, MessageBoxIcon.Error); - return false; + table.Columns.Add(groupNames[i]); } - finally + + if (!string.IsNullOrEmpty(tbTestLine.Text)) { - dataGridView1.DataSource = table; + Match match = regex.Match(tbTestLine.Text); + var row = table.NewRow(); + var values = match.Groups.OfType().Skip(offset).Select(group => group.Value).Cast().ToArray(); + row.ItemArray = values; + table.Rows.Add(row); } + + return true; + } + catch (Exception ex) + { + MessageBox.Show($@"Invalid Regex !{Environment.NewLine}{ex.Message}", @"Regex Columnizer Configuration", MessageBoxButtons.OK, MessageBoxIcon.Error); + return false; + } + finally + { + dataGridView1.DataSource = table; } } } diff --git a/src/SftpFileSystemx64/ConfigData.cs b/src/SftpFileSystemx64/ConfigData.cs index 800005ce..02b58e21 100644 --- a/src/SftpFileSystemx64/ConfigData.cs +++ b/src/SftpFileSystemx64/ConfigData.cs @@ -1,15 +1,14 @@ -namespace SftpFileSystem +namespace SftpFileSystem; + +public class ConfigData { - public class ConfigData - { - #region Properties + #region Properties - public string KeyFile { get; set; } + public string KeyFile { get; set; } - public bool UseKeyfile { get; set; } + public bool UseKeyfile { get; set; } - public KeyType KeyType { get; set; } + public KeyType KeyType { get; set; } - #endregion - } + #endregion } \ No newline at end of file diff --git a/src/SftpFileSystemx64/ConfigDialog.cs b/src/SftpFileSystemx64/ConfigDialog.cs index f7f963db..c3515d9d 100644 --- a/src/SftpFileSystemx64/ConfigDialog.cs +++ b/src/SftpFileSystemx64/ConfigDialog.cs @@ -4,68 +4,67 @@ using System.Windows.Forms; [assembly: SupportedOSPlatform("windows")] -namespace SftpFileSystem -{ - public partial class ConfigDialog : Form - { - #region Ctor +namespace SftpFileSystem; - public ConfigDialog(ConfigData configData) - { - SuspendLayout(); - AutoScaleDimensions = new SizeF(96F, 96F); - AutoScaleMode = AutoScaleMode.Dpi; - InitializeComponent(); - TopLevel = false; - ConfigData = configData; - chkBoxPK.Checked = ConfigData.UseKeyfile; - radioBtnPuttyKey.Checked = ConfigData.KeyType == KeyType.Putty; - radioBtnSSHKey.Checked = ConfigData.KeyType == KeyType.Ssh; - lblFile.Text = ConfigData.KeyFile; - ResumeLayout(); - } +public partial class ConfigDialog : Form +{ + #region Ctor - #endregion + public ConfigDialog(ConfigData configData) + { + SuspendLayout(); + AutoScaleDimensions = new SizeF(96F, 96F); + AutoScaleMode = AutoScaleMode.Dpi; + InitializeComponent(); + TopLevel = false; + ConfigData = configData; + chkBoxPK.Checked = ConfigData.UseKeyfile; + radioBtnPuttyKey.Checked = ConfigData.KeyType == KeyType.Putty; + radioBtnSSHKey.Checked = ConfigData.KeyType == KeyType.Ssh; + lblFile.Text = ConfigData.KeyFile; + ResumeLayout(); + } - #region Properties / Indexers + #endregion - public ConfigData ConfigData { get; } + #region Properties / Indexers - #endregion + public ConfigData ConfigData { get; } - #region Event handling Methods + #endregion - private void OnBtnKeyFileClick(object sender, EventArgs e) - { - FileDialog dlg = new OpenFileDialog(); - if (DialogResult.OK == dlg.ShowDialog()) - { - ConfigData.KeyFile = dlg.FileName; - lblFile.Text = ConfigData.KeyFile; - } - } + #region Event handling Methods - private void OnChkBoxPKCheckedChanged(object sender, EventArgs e) + private void OnBtnKeyFileClick(object sender, EventArgs e) + { + FileDialog dlg = new OpenFileDialog(); + if (DialogResult.OK == dlg.ShowDialog()) { - ConfigData.UseKeyfile = chkBoxPK.Checked; + ConfigData.KeyFile = dlg.FileName; + lblFile.Text = ConfigData.KeyFile; } + } - private void OnChkBoxPKCheckStateChanged(object sender, EventArgs e) - { - keyFileButton.Enabled = chkBoxPK.Checked; - keyTypeGroupBox.Enabled = chkBoxPK.Checked; - } + private void OnChkBoxPKCheckedChanged(object sender, EventArgs e) + { + ConfigData.UseKeyfile = chkBoxPK.Checked; + } - private void OnRadioButtonPuttyKeyCheckedChanged(object sender, EventArgs e) - { - ConfigData.KeyType = KeyType.Putty; - } + private void OnChkBoxPKCheckStateChanged(object sender, EventArgs e) + { + keyFileButton.Enabled = chkBoxPK.Checked; + keyTypeGroupBox.Enabled = chkBoxPK.Checked; + } - private void OnRadioButtonSSHKeyCheckedChanged(object sender, EventArgs e) - { - ConfigData.KeyType = KeyType.Ssh; - } + private void OnRadioButtonPuttyKeyCheckedChanged(object sender, EventArgs e) + { + ConfigData.KeyType = KeyType.Putty; + } - #endregion + private void OnRadioButtonSSHKeyCheckedChanged(object sender, EventArgs e) + { + ConfigData.KeyType = KeyType.Ssh; } + + #endregion } diff --git a/src/SftpFileSystemx64/CredentialCache.cs b/src/SftpFileSystemx64/CredentialCache.cs index 5838be12..93571c2b 100644 --- a/src/SftpFileSystemx64/CredentialCache.cs +++ b/src/SftpFileSystemx64/CredentialCache.cs @@ -1,60 +1,59 @@ using System.Collections.Generic; -namespace SftpFileSystem +namespace SftpFileSystem; + +internal class CredentialCache { - internal class CredentialCache - { - #region Private Fields + #region Private Fields - private readonly IList _credList = []; + private readonly IList _credList = []; - #endregion + #endregion - #region Private Methods + #region Private Methods - private void RemoveCredentials(string host, string user) + private void RemoveCredentials(string host, string user) + { + Credentials credentials = GetCredentials(host, user); + if (credentials != null) { - Credentials credentials = GetCredentials(host, user); - if (credentials != null) - { - _credList.Remove(credentials); - } + _credList.Remove(credentials); } + } - #endregion + #endregion - internal IList GetUsersForHost(string host) - { - IList result = []; + internal IList GetUsersForHost(string host) + { + IList result = []; - foreach (Credentials cred in _credList) + foreach (Credentials cred in _credList) + { + if (cred.Host.Equals(host)) { - if (cred.Host.Equals(host)) - { - result.Add(cred.UserName); - } + result.Add(cred.UserName); } - - return result; } - internal Credentials GetCredentials(string host, string user) + return result; + } + + internal Credentials GetCredentials(string host, string user) + { + foreach (Credentials cred in _credList) { - foreach (Credentials cred in _credList) + if (cred.Host.Equals(host) && cred.UserName.Equals(user)) { - if (cred.Host.Equals(host) && cred.UserName.Equals(user)) - { - return cred; - } + return cred; } - - return null; } - internal void Add(Credentials cred) - { - RemoveCredentials(cred.Host, cred.UserName); - _credList.Add(cred); - } + return null; + } + + internal void Add(Credentials cred) + { + RemoveCredentials(cred.Host, cred.UserName); + _credList.Add(cred); } } diff --git a/src/SftpFileSystemx64/Credentials.cs b/src/SftpFileSystemx64/Credentials.cs index 8bdcdf5d..fbd7cecf 100644 --- a/src/SftpFileSystemx64/Credentials.cs +++ b/src/SftpFileSystemx64/Credentials.cs @@ -1,26 +1,25 @@ -namespace SftpFileSystem +namespace SftpFileSystem; + +internal class Credentials { - internal class Credentials - { - #region Ctor + #region Ctor - internal Credentials(string host, string userName, string password) - { - Host = host; - UserName = userName; - Password = password; - } + internal Credentials(string host, string userName, string password) + { + Host = host; + UserName = userName; + Password = password; + } - #endregion + #endregion - #region Properties / Indexers + #region Properties / Indexers - public string Host { get; } + public string Host { get; } - public string Password { get; } + public string Password { get; } - public string UserName { get; } + public string UserName { get; } - #endregion - } + #endregion } diff --git a/src/SftpFileSystemx64/FailedKeyDialog.cs b/src/SftpFileSystemx64/FailedKeyDialog.cs index 6a728c3e..6084c33d 100644 --- a/src/SftpFileSystemx64/FailedKeyDialog.cs +++ b/src/SftpFileSystemx64/FailedKeyDialog.cs @@ -2,43 +2,42 @@ using System.Drawing; using System.Windows.Forms; -namespace SftpFileSystem +namespace SftpFileSystem; + +public partial class FailedKeyDialog : Form { - public partial class FailedKeyDialog : Form + #region Ctor + + public FailedKeyDialog() + { + SuspendLayout(); + AutoScaleDimensions = new SizeF(96F, 96F); + AutoScaleMode = AutoScaleMode.Dpi; + InitializeComponent(); + ResumeLayout(); + } + + #endregion + + #region Event handling Methods + + private void OnBtnCancelClick(object sender, EventArgs e) { - #region Ctor - - public FailedKeyDialog() - { - SuspendLayout(); - AutoScaleDimensions = new SizeF(96F, 96F); - AutoScaleMode = AutoScaleMode.Dpi; - InitializeComponent(); - ResumeLayout(); - } - - #endregion - - #region Event handling Methods - - private void OnBtnCancelClick(object sender, EventArgs e) - { - DialogResult = DialogResult.Cancel; - Close(); - } - - private void OnBtnRetryClick(object sender, EventArgs e) - { - DialogResult = DialogResult.Retry; - Close(); - } - - private void OnBtnUsePasswordAuthenticationClick(object sender, EventArgs e) - { - DialogResult = DialogResult.OK; - Close(); - } - - #endregion + DialogResult = DialogResult.Cancel; + Close(); } + + private void OnBtnRetryClick(object sender, EventArgs e) + { + DialogResult = DialogResult.Retry; + Close(); + } + + private void OnBtnUsePasswordAuthenticationClick(object sender, EventArgs e) + { + DialogResult = DialogResult.OK; + Close(); + } + + #endregion } diff --git a/src/SftpFileSystemx64/KeyType.cs b/src/SftpFileSystemx64/KeyType.cs index 8d989f34..a6a737c4 100644 --- a/src/SftpFileSystemx64/KeyType.cs +++ b/src/SftpFileSystemx64/KeyType.cs @@ -1,8 +1,7 @@ -namespace SftpFileSystem +namespace SftpFileSystem; + +public enum KeyType { - public enum KeyType - { - Putty, - Ssh - } + Putty, + Ssh } diff --git a/src/SftpFileSystemx64/LoginDialog.cs b/src/SftpFileSystemx64/LoginDialog.cs index 936d0c41..7f9581a7 100644 --- a/src/SftpFileSystemx64/LoginDialog.cs +++ b/src/SftpFileSystemx64/LoginDialog.cs @@ -3,80 +3,79 @@ using System.Drawing; using System.Windows.Forms; -namespace SftpFileSystem +namespace SftpFileSystem; + +public partial class LoginDialog : Form { - public partial class LoginDialog : Form - { - #region Private Fields + #region Private Fields - private string _username; + private string _username; - #endregion + #endregion - #region Ctor + #region Ctor - public LoginDialog(string host, IList userNames, bool hidePasswordField) - { - SuspendLayout(); - AutoScaleDimensions = new SizeF(96F, 96F); - AutoScaleMode = AutoScaleMode.Dpi; + public LoginDialog(string host, IList userNames, bool hidePasswordField) + { + SuspendLayout(); + AutoScaleDimensions = new SizeF(96F, 96F); + AutoScaleMode = AutoScaleMode.Dpi; - InitializeComponent(); - serverNameLabel.Text = host; - if (userNames != null) + InitializeComponent(); + serverNameLabel.Text = host; + if (userNames != null) + { + foreach (var name in userNames) { - foreach (string name in userNames) + if (name != null) { - if (name != null) - { - cmbUsername.Items.Add(name); - } + cmbUsername.Items.Add(name); } } + } - if (hidePasswordField) - { - txtBoxPassword.Enabled = false; - lblPassword.Enabled = false; - } - - ResumeLayout(); + if (hidePasswordField) + { + txtBoxPassword.Enabled = false; + lblPassword.Enabled = false; } - #endregion + ResumeLayout(); + } + + #endregion - #region Properties / Indexers + #region Properties / Indexers - public string Password { get; private set; } + public string Password { get; private set; } - public string Username + public string Username + { + get => _username; + set { - get => _username; - set - { - _username = value ?? string.Empty; - cmbUsername.Text = value; - } + _username = value ?? string.Empty; + cmbUsername.Text = value; } + } - #endregion + #endregion - #region Event handling Methods + #region Event handling Methods - private void OnBtnOKClick(object sender, EventArgs e) - { - Password = txtBoxPassword.Text; - _username = cmbUsername.Text; - } + private void OnBtnOKClick(object sender, EventArgs e) + { + Password = txtBoxPassword.Text; + _username = cmbUsername.Text; + } - private void OnLoginDialogLoad(object sender, EventArgs e) + private void OnLoginDialogLoad(object sender, EventArgs e) + { + if (cmbUsername.Text.Length > 0) { - if (cmbUsername.Text.Length > 0) - { - txtBoxPassword.Focus(); - } + txtBoxPassword.Focus(); } - - #endregion } + + #endregion } diff --git a/src/SftpFileSystemx64/PrivateKeyPasswordDialog.cs b/src/SftpFileSystemx64/PrivateKeyPasswordDialog.cs index 6184f6ab..21c2c269 100644 --- a/src/SftpFileSystemx64/PrivateKeyPasswordDialog.cs +++ b/src/SftpFileSystemx64/PrivateKeyPasswordDialog.cs @@ -2,41 +2,40 @@ using System.Drawing; using System.Windows.Forms; -namespace SftpFileSystem -{ - public partial class PrivateKeyPasswordDialog : Form - { - #region Ctor +namespace SftpFileSystem; - public PrivateKeyPasswordDialog() - { - SuspendLayout(); - AutoScaleDimensions = new SizeF(96F, 96F); - AutoScaleMode = AutoScaleMode.Dpi; - InitializeComponent(); - ResumeLayout(); - } +public partial class PrivateKeyPasswordDialog : Form +{ + #region Ctor - #endregion + public PrivateKeyPasswordDialog() + { + SuspendLayout(); + AutoScaleDimensions = new SizeF(96F, 96F); + AutoScaleMode = AutoScaleMode.Dpi; + InitializeComponent(); + ResumeLayout(); + } - #region Properties / Indexers + #endregion - public string Password { get; private set; } + #region Properties / Indexers - #endregion + public string Password { get; private set; } - #region Event handling Methods + #endregion - private void OnLoginDialogLoad(object sender, EventArgs e) - { - passwordTextBox.Focus(); - } + #region Event handling Methods - private void OnBtnOkClick(object sender, EventArgs e) - { - Password = passwordTextBox.Text; - } + private void OnLoginDialogLoad(object sender, EventArgs e) + { + passwordTextBox.Focus(); + } - #endregion + private void OnBtnOkClick(object sender, EventArgs e) + { + Password = passwordTextBox.Text; } + + #endregion } diff --git a/src/SftpFileSystemx64/SftpFileSystem.cs b/src/SftpFileSystemx64/SftpFileSystem.cs index fbefdff0..d899b430 100644 --- a/src/SftpFileSystemx64/SftpFileSystem.cs +++ b/src/SftpFileSystemx64/SftpFileSystem.cs @@ -8,230 +8,229 @@ using System.Windows.Forms; using System.Xml.Serialization; -namespace SftpFileSystem +namespace SftpFileSystem; + +public class SftpFileSystem : IFileSystemPlugin, ILogExpertPluginConfigurator { - public class SftpFileSystem : IFileSystemPlugin, ILogExpertPluginConfigurator - { - #region Private Fields + #region Private Fields - private readonly ILogExpertLogger _logger; + private readonly ILogExpertLogger _logger; - private ConfigDialog _configDialog; - private volatile PrivateKeyFile _privateKeyFile; + private ConfigDialog _configDialog; + private volatile PrivateKeyFile _privateKeyFile; - #endregion + #endregion - #region Ctor + #region Ctor - public SftpFileSystem(IFileSystemCallback callback) - { - _logger = callback.GetLogger(); - CredentialsCache = new CredentialCache(); - } + public SftpFileSystem(IFileSystemCallback callback) + { + _logger = callback.GetLogger(); + CredentialsCache = new CredentialCache(); + } - #endregion + #endregion - #region Interface IFileSystemPlugin + #region Interface IFileSystemPlugin - public string Description => "Can read log files directly from SFTP server."; + public string Description => "Can read log files directly from SFTP server."; - public string Text => "SFTP plugin"; + public string Text => "SFTP plugin"; - public bool CanHandleUri(string uriString) + public bool CanHandleUri(string uriString) + { + try { - try - { - Uri uri = new(uriString); - return uri.Scheme.Equals("sftp", StringComparison.InvariantCultureIgnoreCase); - } - catch (Exception e) - { - _logger.LogError(e.Message); - return false; - } + Uri uri = new(uriString); + return uri.Scheme.Equals("sftp", StringComparison.InvariantCultureIgnoreCase); } - - public ILogFileInfo GetLogfileInfo(string uriString) + catch (Exception e) { - try - { - Uri uri = new(uriString.Replace('\\', '/')); - return new SftpLogFileInfo(this, uri, _logger); - } - catch (Exception e) - { - _logger.LogError(e.Message); - return null; - } + _logger.LogError(e.Message); + return false; } + } - #endregion - - #region Interface ILogExpertPluginConfigurator - - public bool HasEmbeddedForm() + public ILogFileInfo GetLogfileInfo(string uriString) + { + try { - return true; + Uri uri = new(uriString.Replace('\\', '/')); + return new SftpLogFileInfo(this, uri, _logger); } - - public void HideConfigForm() + catch (Exception e) { - ConfigData = _configDialog.ConfigData; - _configDialog.Hide(); - _configDialog.Dispose(); + _logger.LogError(e.Message); + return null; } + } - public void LoadConfig(string configDir) - { - XmlSerializer xml = new(ConfigData.GetType()); + #endregion - FileInfo configFile = new(configDir + "\\" + "sftpfilesystem.cfg"); + #region Interface ILogExpertPluginConfigurator - if (!configFile.Exists) - { - return; - } + public bool HasEmbeddedForm() + { + return true; + } - FileStream fs = null; + public void HideConfigForm() + { + ConfigData = _configDialog.ConfigData; + _configDialog.Hide(); + _configDialog.Dispose(); + } - try - { - fs = configFile.OpenRead(); + public void LoadConfig(string configDir) + { + XmlSerializer xml = new(ConfigData.GetType()); - ConfigData = (ConfigData)xml.Deserialize(fs); - } - catch (IOException e) - { - _logger.LogError(e.Message); - } - finally - { - fs?.Flush(); - fs?.Close(); - fs?.Dispose(); - } - } + FileInfo configFile = new(configDir + "\\" + "sftpfilesystem.cfg"); - public void SaveConfig(string configDir) + if (!configFile.Exists) { - _logger.Info("Saving SFTP config"); - XmlSerializer xml = new(ConfigData.GetType()); + return; + } - FileStream fs = null; + FileStream fs = null; - try - { - fs = new FileStream(configDir + "\\" + "sftpfilesystem.cfg", FileMode.Create); - xml.Serialize(fs, ConfigData); - fs.Close(); - } - catch (IOException e) - { - _logger.LogError(e.Message); - } - finally - { - fs?.Flush(); - fs?.Close(); - fs?.Dispose(); - } - } + try + { + fs = configFile.OpenRead(); - public void ShowConfigDialog(object owner) + ConfigData = (ConfigData)xml.Deserialize(fs); + } + catch (IOException e) { - throw new NotImplementedException(); + _logger.LogError(e.Message); } - - public void ShowConfigForm(object parentPanel) + finally { - _configDialog = new ConfigDialog(ConfigData) - { - Parent = (Panel)parentPanel - }; - - _configDialog.Show(); + fs?.Flush(); + fs?.Close(); + fs?.Dispose(); } + } + + public void SaveConfig(string configDir) + { + _logger.Info("Saving SFTP config"); + XmlSerializer xml = new(ConfigData.GetType()); - public void StartConfig() + FileStream fs = null; + + try + { + fs = new FileStream(configDir + "\\" + "sftpfilesystem.cfg", FileMode.Create); + xml.Serialize(fs, ConfigData); + fs.Close(); + } + catch (IOException e) + { + _logger.LogError(e.Message); + } + finally { + fs?.Flush(); + fs?.Close(); + fs?.Dispose(); } + } - #endregion + public void ShowConfigDialog(object owner) + { + throw new NotImplementedException(); + } - #region Properties / Indexers + public void ShowConfigForm(object parentPanel) + { + _configDialog = new ConfigDialog(ConfigData) + { + Parent = (Panel)parentPanel + }; - public ConfigData ConfigData { get; private set; } = new ConfigData(); + _configDialog.Show(); + } - public PrivateKeyFile PrivateKeyFile - { - get => _privateKeyFile; - set => _privateKeyFile = value; - } + public void StartConfig() + { + } + + #endregion - private CredentialCache CredentialsCache { get; } + #region Properties / Indexers - #endregion + public ConfigData ConfigData { get; private set; } = new ConfigData(); + + public PrivateKeyFile PrivateKeyFile + { + get => _privateKeyFile; + set => _privateKeyFile = value; + } - internal Credentials GetCredentials(Uri uri, bool cacheAllowed, bool hidePasswordField) + private CredentialCache CredentialsCache { get; } + + #endregion + + internal Credentials GetCredentials(Uri uri, bool cacheAllowed, bool hidePasswordField) + { + // Synchronized access to the GetCredentials() method prevents multiple login dialogs when loading multiple files at once + // (e.g. on startup). So the user only needs to enter credentials once for the same host. + lock (this) { - // Synchronized access to the GetCredentials() method prevents multiple login dialogs when loading multiple files at once - // (e.g. on startup). So the user only needs to enter credentials once for the same host. - lock (this) + string userName = null; + string password = null; + if (uri.UserInfo != null && uri.UserInfo.Length > 0) { - string userName = null; - string password = null; - if (uri.UserInfo != null && uri.UserInfo.Length > 0) + var split = uri.UserInfo.Split(':'); + if (split.Length > 0) { - string[] split = uri.UserInfo.Split(':'); - if (split.Length > 0) - { - userName = split[0]; - } - - if (split.Length > 1) - { - password = split[1]; - } + userName = split[0]; } - IList usersForHost = CredentialsCache.GetUsersForHost(uri.Host); - if (userName == null && cacheAllowed) + if (split.Length > 1) { - if (usersForHost.Count == 1) - { - userName = usersForHost[0]; - } + password = split[1]; } + } - if (userName != null && password == null && cacheAllowed) + IList usersForHost = CredentialsCache.GetUsersForHost(uri.Host); + if (userName == null && cacheAllowed) + { + if (usersForHost.Count == 1) { - Credentials cred = CredentialsCache.GetCredentials(uri.Host, userName); - if (cred != null) - { - return cred; - } + userName = usersForHost[0]; } + } + + if (userName != null && password == null && cacheAllowed) + { + Credentials cred = CredentialsCache.GetCredentials(uri.Host, userName); + if (cred != null) + { + return cred; + } + } - if (userName == null || password == null) + if (userName == null || password == null) + { + LoginDialog dlg = new(uri.Host, usersForHost, hidePasswordField) { - LoginDialog dlg = new(uri.Host, usersForHost, hidePasswordField) - { - Username = userName - }; - - if (DialogResult.OK == dlg.ShowDialog()) - { - password = dlg.Password; - userName = dlg.Username; - } - - dlg.Dispose(); + Username = userName + }; + + if (DialogResult.OK == dlg.ShowDialog()) + { + password = dlg.Password; + userName = dlg.Username; } - Credentials credentials = new(uri.Host, userName, password); - CredentialsCache.Add(credentials); - return credentials; + dlg.Dispose(); } + + Credentials credentials = new(uri.Host, userName, password); + CredentialsCache.Add(credentials); + return credentials; } } } diff --git a/src/SftpFileSystemx64/SftpLogFileInfo.cs b/src/SftpFileSystemx64/SftpLogFileInfo.cs index 6323c202..5784dc9c 100644 --- a/src/SftpFileSystemx64/SftpLogFileInfo.cs +++ b/src/SftpFileSystemx64/SftpLogFileInfo.cs @@ -1,263 +1,264 @@ -using System; +using System; using System.IO; using System.Threading; using System.Windows.Forms; + using LogExpert; + using Renci.SshNet; using Renci.SshNet.Sftp; -namespace SftpFileSystem +namespace SftpFileSystem; + +internal class SftpLogFileInfo : ILogFileInfo { - internal class SftpLogFileInfo : ILogFileInfo - { - #region Static/Constants - //TODO Add to Options - private const int RETRY_COUNT = 20; - private const int RETRY_SLEEP = 250; + #region Static/Constants + //TODO Add to Options + private const int RETRY_COUNT = 20; + private const int RETRY_SLEEP = 250; - #endregion + #endregion - #region Private Fields + #region Private Fields - private readonly ILogExpertLogger _logger; - private readonly string _remoteFileName; + private readonly ILogExpertLogger _logger; + private readonly string _remoteFileName; - private readonly SftpClient _sftp; - private readonly object _sshKeyMonitor = new(); - private DateTime _lastChange = DateTime.Now; - private long _lastLength; + private readonly SftpClient _sftp; + private readonly object _sshKeyMonitor = new(); + private DateTime _lastChange = DateTime.Now; + private long _lastLength; - #endregion + #endregion - #region Ctor + #region Ctor - internal SftpLogFileInfo(SftpFileSystem sftpFileSystem, Uri fileUri, ILogExpertLogger logger) - { - _logger = logger; - SftpFileSystem sftFileSystem = sftpFileSystem; - Uri = fileUri; - _remoteFileName = Uri.PathAndQuery; + internal SftpLogFileInfo (SftpFileSystem sftpFileSystem, Uri fileUri, ILogExpertLogger logger) + { + _logger = logger; + SftpFileSystem sftFileSystem = sftpFileSystem; + Uri = fileUri; + _remoteFileName = Uri.PathAndQuery; - int port = Uri.Port != -1 ? Uri.Port : 22; + var port = Uri.Port != -1 ? Uri.Port : 22; - bool success = false; - bool cancelled = false; - if (sftFileSystem.ConfigData.UseKeyfile) + var success = false; + var cancelled = false; + if (sftFileSystem.ConfigData.UseKeyfile) + { + lock (_sshKeyMonitor) // prevent multiple password dialogs when opening multiple files at once { - lock (_sshKeyMonitor) // prevent multiple password dialogs when opening multiple files at once + while (sftFileSystem.PrivateKeyFile == null) { - while (sftFileSystem.PrivateKeyFile == null) + PrivateKeyPasswordDialog dlg = new(); + DialogResult dialogResult = dlg.ShowDialog(); + if (dialogResult == DialogResult.Cancel) { - PrivateKeyPasswordDialog dlg = new(); - DialogResult dialogResult = dlg.ShowDialog(); - if (dialogResult == DialogResult.Cancel) - { - cancelled = true; - break; - } + cancelled = true; + break; + } - PrivateKeyFile privateKeyFile = new(sftFileSystem.ConfigData.KeyFile, dlg.Password); + PrivateKeyFile privateKeyFile = new(sftFileSystem.ConfigData.KeyFile, dlg.Password); - if (privateKeyFile != null) - { - sftFileSystem.PrivateKeyFile = privateKeyFile; - } - else - { - MessageBox.Show("Loading key file failed"); - } + if (privateKeyFile != null) + { + sftFileSystem.PrivateKeyFile = privateKeyFile; + } + else + { + MessageBox.Show("Loading key file failed"); } } + } - if (cancelled == false) + if (cancelled == false) + { + success = false; + Credentials credentials = sftFileSystem.GetCredentials(Uri, true, true); + while (success == false) { - success = false; - Credentials credentials = sftFileSystem.GetCredentials(Uri, true, true); - while (success == false) + //Add ConnectionInfo object + _sftp = new SftpClient(Uri.Host, credentials.UserName, sftFileSystem.PrivateKeyFile); + + if (_sftp != null) { - //Add ConnectionInfo object - _sftp = new SftpClient(Uri.Host, credentials.UserName, sftFileSystem.PrivateKeyFile); + _sftp.Connect(); + success = true; + } - if (_sftp != null) + if (success == false) + { + FailedKeyDialog dlg = new(); + DialogResult res = dlg.ShowDialog(); + dlg.Dispose(); + if (res == DialogResult.Cancel) { - _sftp.Connect(); - success = true; + return; } - if (success == false) + if (res == DialogResult.OK) { - FailedKeyDialog dlg = new(); - DialogResult res = dlg.ShowDialog(); - dlg.Dispose(); - if (res == DialogResult.Cancel) - { - return; - } - - if (res == DialogResult.OK) - { - break; // go to user/pw auth - } - - // retries with disabled cache - credentials = sftFileSystem.GetCredentials(Uri, false, true); + break; // go to user/pw auth } + + // retries with disabled cache + credentials = sftFileSystem.GetCredentials(Uri, false, true); } } } + } - if (success == false) + if (success == false) + { + // username/password auth + Credentials credentials = sftFileSystem.GetCredentials(Uri, true, false); + _sftp = new SftpClient(Uri.Host, port, credentials.UserName, credentials.Password); + + if (_sftp == null) { - // username/password auth - Credentials credentials = sftFileSystem.GetCredentials(Uri, true, false); + // first fail -> try again with disabled cache + credentials = sftFileSystem.GetCredentials(Uri, false, false); _sftp = new SftpClient(Uri.Host, port, credentials.UserName, credentials.Password); if (_sftp == null) { - // first fail -> try again with disabled cache - credentials = sftFileSystem.GetCredentials(Uri, false, false); - _sftp = new SftpClient(Uri.Host, port, credentials.UserName, credentials.Password); - - if (_sftp == null) - { - // 2nd fail -> abort - MessageBox.Show("Authentication failed!"); - //MessageBox.Show(sftp.LastErrorText); - return; - } - } - else - { - _sftp.Connect(); + // 2nd fail -> abort + MessageBox.Show("Authentication failed!"); + //MessageBox.Show(sftp.LastErrorText); + return; } } - - if (_sftp.IsConnected == false) + else { - MessageBox.Show("Sftp is not connected"); - return; + _sftp.Connect(); } + } - OriginalLength = _lastLength = Length; + if (_sftp.IsConnected == false) + { + MessageBox.Show("Sftp is not connected"); + return; } - #endregion + OriginalLength = _lastLength = Length; + } - #region Interface ILogFileInfo + #endregion - public string DirectoryName + #region Interface ILogFileInfo + + public string DirectoryName + { + get { - get + var full = FullName; + var i = full.LastIndexOf(DirectorySeparatorChar); + if (i != -1) { - string full = FullName; - int i = full.LastIndexOf(DirectorySeparatorChar); - if (i != -1) - { - return full.Substring(0, i); - } - - return "."; + return full.Substring(0, i); } + + return "."; } + } - public char DirectorySeparatorChar => '/'; + public char DirectorySeparatorChar => '/'; - public bool FileExists + public bool FileExists + { + get { - get + try { - try - { - SftpFile file = (SftpFile) _sftp.Get(_remoteFileName); - long len = file.Attributes.Size; - return len != -1; - } - catch (Exception e) - { - _logger.LogError(e.Message); - return false; - } + var file = (SftpFile)_sftp.Get(_remoteFileName); + var len = file.Attributes.Size; + return len != -1; + } + catch (Exception e) + { + _logger.LogError(e.Message); + return false; } } + } - public string FileName + public string FileName + { + get { - get - { - string full = FullName; - int i = full.LastIndexOf(DirectorySeparatorChar); - return full.Substring(i + 1); - } + var full = FullName; + var i = full.LastIndexOf(DirectorySeparatorChar); + return full.Substring(i + 1); } + } - public string FullName => Uri.ToString(); + public string FullName => Uri.ToString(); - public long Length + public long Length + { + get { - get - { - SftpFile file = (SftpFile)_sftp.Get(_remoteFileName); - return file.Attributes.Size; - } + var file = (SftpFile)_sftp.Get(_remoteFileName); + return file.Attributes.Size; } + } - public long OriginalLength { get; } + public long OriginalLength { get; } - public int PollInterval + public int PollInterval + { + get { - get + TimeSpan diff = DateTime.Now - _lastChange; + if (diff.TotalSeconds < 4) { - TimeSpan diff = DateTime.Now - _lastChange; - if (diff.TotalSeconds < 4) - { - return 400; - } - - if (diff.TotalSeconds < 30) - { - return (int)diff.TotalSeconds * 100; - } + return 400; + } - return 5000; + if (diff.TotalSeconds < 30) + { + return (int)diff.TotalSeconds * 100; } + + return 5000; } + } - public Uri Uri { get; } + public Uri Uri { get; } - public bool FileHasChanged() + public bool FileHasChanged () + { + if (Length != _lastLength) { - if (Length != _lastLength) - { - _lastLength = Length; - _lastChange = DateTime.Now; - return true; - } - - return false; + _lastLength = Length; + _lastChange = DateTime.Now; + return true; } - public Stream OpenStream() + return false; + } + + public Stream OpenStream () + { + var retry = RETRY_COUNT; + while (true) { - int retry = RETRY_COUNT; - while (true) + try { - try + return _sftp.OpenRead(_remoteFileName); + } + catch (IOException) + { + //First remove a try then check if its less or 0 + if (--retry <= 0) { - return _sftp.OpenRead(_remoteFileName); + throw; } - catch (IOException) - { - //First remove a try then check if its less or 0 - if (--retry <= 0) - { - throw; - } - Thread.Sleep(RETRY_SLEEP); - } + Thread.Sleep(RETRY_SLEEP); } } - - #endregion } + + #endregion }