js8call/JS8_Main/TraceFile.cpp
Chris-AC9KH 356bdc0f50 Code cleanup - move loose source and header files in source tree to group folders
Rename all header files with .h extension
Fix function declaration in HamlibTransceiver.h that overrode member function but was not marked override
Remove unused variable in Modulator.cpp
Remove unused files from source tree
Remove duplicate LazyFillComboBox files
Reformat codebase to LLVM C++ standard
2026-01-02 16:46:38 -06:00

108 lines
2.9 KiB
C++

#include "TraceFile.h"
#include <stdexcept>
#include <QDateTime>
#include <QDebug>
#include <QFile>
#include <QMessageLogContext>
#include <QMutex>
#include <QMutexLocker>
#include <QString>
#include <QTextStream>
#include "JS8_Include/pimpl_impl.h"
namespace {
QMutex lock;
}
class TraceFile::impl {
public:
impl(QString const &trace_file_path);
~impl();
// no copying
impl(impl const &) = delete;
impl &operator=(impl const &) = delete;
private:
// write Qt messages to the diagnostic log file
static void message_handler(QtMsgType type,
QMessageLogContext const &context,
QString const &msg);
QFile file_;
QTextStream stream_;
QTextStream *original_stream_;
QtMessageHandler original_handler_;
static QTextStream *current_stream_;
};
QTextStream *TraceFile::impl::current_stream_;
// delegate to implementation class
TraceFile::TraceFile(QString const &trace_file_path) : m_{trace_file_path} {}
TraceFile::~TraceFile() {}
TraceFile::impl::impl(QString const &trace_file_path)
: file_{trace_file_path}, original_stream_{current_stream_},
original_handler_{nullptr} {
// if the log file is writeable; initialise diagnostic logging to it
// for append and hook up the Qt global message handler
if (file_.open(QFile::WriteOnly | QFile::Append | QFile::Text)) {
stream_.setDevice(&file_);
current_stream_ = &stream_;
original_handler_ = qInstallMessageHandler(message_handler);
}
}
TraceFile::impl::~impl() {
// unhook our message handler before the stream and file are destroyed
if (original_handler_) {
qInstallMessageHandler(original_handler_);
}
current_stream_ = original_stream_; // revert to prior stream
}
// write Qt messages to the diagnostic log file
void TraceFile::impl::message_handler(QtMsgType type,
QMessageLogContext const &context,
QString const &msg) {
char const *severity;
switch (type) {
case QtDebugMsg:
severity = "Debug";
break;
case QtWarningMsg:
severity = "Warning";
break;
case QtFatalMsg:
severity = "Fatal";
break;
default:
severity = "Critical";
break;
}
{
// guard against multiple threads with overlapping messages
QMutexLocker guard(&lock);
Q_ASSERT_X(current_stream_, "TraceFile:message_handler",
"no stream to write to");
*current_stream_
<< QDateTime::currentDateTimeUtc().toString(
"yyyy-MM-ddTHH:mm:ss.zzzZ")
<< '(' << context.file << ':'
<< context.line /* << ", " << context.function */ << ')' << severity
<< ": " << msg.trimmed() << Qt::endl;
}
if (QtFatalMsg == type) {
throw std::runtime_error{"Fatal Qt Error"};
}
}