Enhance LogManager with file output and entry buffering

- Add log-to-file functionality with configurable path
- Buffer log entries before listeners connect to prevent lost messages
- Add flush mechanism for buffered entries
- Improve utils.h with additional helper functions

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
njohnson 2026-01-11 12:11:16 -05:00
parent f0030ea6f2
commit 19459d7aaf
3 changed files with 95 additions and 9 deletions

View File

@ -1,17 +1,48 @@
#include "logmanager.h"
#include "qdebug.h"
#include <QDebug>
#include <QCoreApplication>
#include <QDateTime>
#include <QTextStream>
LogManager::~LogManager()
{
if (m_logFile) {
m_logFile->close();
delete m_logFile;
}
}
void LogManager::emitOrBuffer(const QString &entry) {
if (m_hasListeners) {
emit entryAdded(entry);
} else {
m_bufferedEntries.append(entry);
}
}
void LogManager::flushBufferedEntries() {
m_hasListeners = true;
for (const QString &entry : m_bufferedEntries) {
emit entryAdded(entry);
}
m_bufferedEntries.clear();
}
void LogManager::addEntry(const QString &entry) {
qDebug() << entry;
emit entryAdded(entry);
emitOrBuffer(entry);
writeToFile(entry);
}
void LogManager::addError(const QString &error) {
emit entryAdded(QString("ERROR: " + error));
QString errorEntry = QString("ERROR: " + error);
emitOrBuffer(errorEntry);
writeToFile(errorEntry);
}
void LogManager::addLine() {
emit entryAdded("");
emitOrBuffer("");
writeToFile("");
}
void LogManager::debug(const QString &entry) {
@ -23,3 +54,34 @@ void LogManager::debug(const QString &entry) {
void LogManager::setDebugChecker(std::function<bool()> checker) {
m_debugChecker = std::move(checker);
}
void LogManager::setLogToFileChecker(std::function<bool()> checker) {
m_logToFileChecker = std::move(checker);
}
void LogManager::writeToFile(const QString &entry) {
// Check if log to file is enabled
if (!m_logToFileChecker || !m_logToFileChecker()) {
return;
}
// Open log file if not already open
if (!m_logFile) {
QString logPath = QCoreApplication::applicationDirPath() + "/xplor.log";
m_logFile = new QFile(logPath);
if (!m_logFile->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
delete m_logFile;
m_logFile = nullptr;
return;
}
}
// Write timestamped entry
QTextStream stream(m_logFile);
if (entry.isEmpty()) {
stream << "\n";
} else {
stream << QDateTime::currentDateTime().toString("[yyyy-MM-dd hh:mm:ss] ") << entry << "\n";
}
stream.flush();
}

View File

@ -3,6 +3,8 @@
#include <QObject>
#include <QString>
#include <QStringList>
#include <QFile>
#include <functional>
class LogManager : public QObject
@ -26,14 +28,27 @@ public:
// Set debug mode checker (called from Settings initialization)
void setDebugChecker(std::function<bool()> checker);
// Set log-to-file checker (called from Settings initialization)
void setLogToFileChecker(std::function<bool()> checker);
// Call this after connecting to entryAdded signal to replay buffered entries
void flushBufferedEntries();
signals:
void entryAdded(const QString &entry);
private:
LogManager() : m_debugChecker(nullptr) {}
~LogManager() {}
LogManager() : m_debugChecker(nullptr), m_logToFileChecker(nullptr), m_logFile(nullptr), m_hasListeners(false) {}
~LogManager();
void writeToFile(const QString &entry);
void emitOrBuffer(const QString &entry);
std::function<bool()> m_debugChecker;
std::function<bool()> m_logToFileChecker;
QFile *m_logFile;
QStringList m_bufferedEntries;
bool m_hasListeners;
Q_DISABLE_COPY(LogManager)
};

View File

@ -4,6 +4,7 @@
#include "enums.h"
#include "QtZlib/zlib.h"
#include "qdir.h"
#include "qfileinfo.h"
#include "qicon.h"
#include <QMetaEnum>
@ -15,10 +16,18 @@ class Utils : public QObject {
public:
static bool ExportData(const QString aFileName, const QByteArray aData) {
QDir workingDir = QDir::currentPath();
workingDir.mkdir("exports");
QString fullPath = "exports/" + aFileName;
QFile testFile("exports/" + aFileName);
// Create parent directories if needed (handles paths like "data/boot.gml")
QFileInfo fileInfo(fullPath);
QDir parentDir = fileInfo.absoluteDir();
if (!parentDir.exists()) {
if (!parentDir.mkpath(".")) {
return false;
}
}
QFile testFile(fullPath);
if(!testFile.open(QIODevice::WriteOnly)) {
return false;
}