Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 41 additions & 1 deletion src/LogExpert.Configuration/ConfigManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public class ConfigManager : IConfigManager
};

private const string SETTINGS_FILE_NAME = "settings.json";
private const int MAX_FILE_HISTORY = 10;

#endregion

Expand Down Expand Up @@ -251,6 +252,43 @@ public void ImportHighlightSettings (FileInfo fileInfo, ExportImportFlags import
Save(SettingsFlags.All);
}

/// <summary>
/// Adds the specified file name to the file history list, moving it to the top if it already exists.
/// </summary>
/// <remarks>If the file name already exists in the history, it is moved to the top of the list. The file
/// history list is limited to a maximum number of entries; the oldest entries are removed if the limit is exceeded.
/// This method is supported only on Windows platforms.</remarks>
/// <param name="fileName">The name of the file to add to the file history list. Comparison is case-insensitive.</param>
[SupportedOSPlatform("windows")]
public void AddToFileHistory (string fileName)
{
bool findName (string s) => s.ToUpperInvariant().Equals(fileName.ToUpperInvariant(), StringComparison.Ordinal);

var index = Instance.Settings.FileHistoryList.FindIndex(findName);

if (index != -1)
{
Instance.Settings.FileHistoryList.RemoveAt(index);
}

Instance.Settings.FileHistoryList.Insert(0, fileName);

while (Instance.Settings.FileHistoryList.Count > MAX_FILE_HISTORY)
{
Instance.Settings.FileHistoryList.RemoveAt(Instance.Settings.FileHistoryList.Count - 1);
}

Save(SettingsFlags.FileHistory);
}

public void ClearLastOpenFilesList ()
{
lock (_loadSaveLock)
{
Instance.Settings.LastOpenFilesList.Clear();
}
}

#endregion

#region Private Methods
Expand Down Expand Up @@ -807,7 +845,8 @@ IOException or
NotSupportedException or
PathTooLongException or
UnauthorizedAccessException or
SecurityException)
SecurityException or
JsonSerializationException)
{
_logger.Error($"Error while deserializing config data: {e}");
newGroups = [];
Expand Down Expand Up @@ -1060,6 +1099,7 @@ private bool ValidateSettings (Settings settings)

return true;
}

#endregion

/// <summary>
Expand Down
71 changes: 71 additions & 0 deletions src/LogExpert.Core/Classes/Persister/PersisterHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System.Collections.ObjectModel;

using LogExpert.Core.Interface;

namespace LogExpert.Core.Classes.Persister;

public static class PersisterHelpers
{

private const string LOCAL_FILE_SYSTEM_NAME = "LocalFileSystem";

/// <summary>
/// Checks if the file name is a settings file (.lxp). If so, the contained logfile name
/// is returned. If not, the given file name is returned unchanged.
/// </summary>
/// <param name="fileName">The file name to resolve</param>
/// <param name="pluginRegistry">Plugin registry for file system resolution (optional)</param>
/// <returns>The resolved log file path</returns>
public static string FindFilenameForSettings (string fileName, IPluginRegistry pluginRegistry)
{
ArgumentException.ThrowIfNullOrWhiteSpace(fileName, nameof(fileName));

if (fileName.EndsWith(".lxp", StringComparison.OrdinalIgnoreCase))
{
var persistenceData = Persister.Load(fileName);
if (persistenceData == null)
{
return fileName;
}

if (!string.IsNullOrEmpty(persistenceData.FileName))
{
if (pluginRegistry != null)
{
var fs = pluginRegistry.FindFileSystemForUri(persistenceData.FileName);
// Use file system plugin for non-local files (network, SFTP, etc.)
if (fs != null && fs.GetType().Name != LOCAL_FILE_SYSTEM_NAME)
{
return persistenceData.FileName;
}
}

// Handle rooted paths (absolute paths)
if (Path.IsPathRooted(persistenceData.FileName))
{
return persistenceData.FileName;
}

// Handle relative paths in .lxp files
var dir = Path.GetDirectoryName(fileName);
return Path.Join(dir, persistenceData.FileName);
}
}

return fileName;
}

public static ReadOnlyCollection<string> FindFilenameForSettings (ReadOnlyCollection<string> fileNames, IPluginRegistry pluginRegistry)
{
ArgumentNullException.ThrowIfNull(fileNames);

var foundFiles = new List<string>(fileNames.Count);

foreach (var fileName in fileNames)
{
foundFiles.Add(FindFilenameForSettings(fileName, pluginRegistry));
}

return foundFiles.AsReadOnly();
}
}
3 changes: 2 additions & 1 deletion src/LogExpert.Core/Classes/Persister/PersisterXML.cs
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,8 @@ public static PersistenceData Load (string fileName)
}
catch (Exception xmlParsingException) when (xmlParsingException is XmlException or
UnauthorizedAccessException or
IOException)
IOException or
FileNotFoundException)
{
_logger.Error(xmlParsingException, $"Error loading persistence data from {fileName}, unknown format, parsing xml or json was not possible");
return null;
Expand Down
5 changes: 5 additions & 0 deletions src/LogExpert.Core/Classes/Persister/ProjectData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,10 @@ public class ProjectData
/// </summary>
public string TabLayoutXml { get; set; }

/// <summary>
/// Gets or sets the full file path to the project file.
/// </summary>
public string ProjectFilePath { get; set; }

#endregion
}
34 changes: 34 additions & 0 deletions src/LogExpert.Core/Classes/Persister/ProjectFileResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System.Collections.ObjectModel;

using LogExpert.Core.Interface;

namespace LogExpert.Core.Classes.Persister;

/// <summary>
/// Helper class to resolve project file references to actual log files.
/// Handles .lxp (persistence) files by extracting the actual log file path.
/// </summary>
public static class ProjectFileResolver
{
/// <summary>
/// Resolves project file names to actual log files.
/// If a file is a .lxp persistence file, extracts the log file path from it.
/// </summary>
/// <param name="projectData">The project data containing file references</param>
/// <param name="pluginRegistry">Plugin registry for file system resolution (optional)</param>
/// <returns>List of tuples containing (logFilePath, originalFilePath)</returns>
public static ReadOnlyCollection<(string LogFile, string OriginalFile)> ResolveProjectFiles (ProjectData projectData, IPluginRegistry pluginRegistry = null)
{
ArgumentNullException.ThrowIfNull(projectData);

var resolved = new List<(string LogFile, string OriginalFile)>();

foreach (var fileName in projectData.FileNames)
{
var logFile = PersisterHelpers.FindFilenameForSettings(fileName, pluginRegistry);
resolved.Add((logFile, fileName));
}

return resolved.AsReadOnly();
}
}
Loading