parent
98ef0e33c8
commit
b7d44f76f6
Binary file not shown.
@ -0,0 +1,476 @@
|
|||||||
|
/**
|
||||||
|
* @file SystemLogPanel.cpp
|
||||||
|
* @brief 系统日志面板界面组件实现
|
||||||
|
* @author Qt UI Developer Expert
|
||||||
|
* @date 2024-12-21
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ui/components/SystemLogPanel.h"
|
||||||
|
#include "utils/SystemLogger.h"
|
||||||
|
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QTextEdit>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QScrollBar>
|
||||||
|
#include <QTextCursor>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
// 静态常量定义
|
||||||
|
const int SystemLogPanel::MAX_LOG_LINES = 500;
|
||||||
|
const int SystemLogPanel::STATUS_UPDATE_INTERVAL = 2000; // 2秒
|
||||||
|
|
||||||
|
SystemLogPanel::SystemLogPanel(QWidget *parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
, m_logTextEdit(nullptr)
|
||||||
|
, m_clearButton(nullptr)
|
||||||
|
, m_pauseButton(nullptr)
|
||||||
|
, m_levelFilter(nullptr)
|
||||||
|
, m_statusLabel(nullptr)
|
||||||
|
, m_titleLabel(nullptr)
|
||||||
|
, m_mainLayout(nullptr)
|
||||||
|
, m_controlLayout(nullptr)
|
||||||
|
, m_statusLayout(nullptr)
|
||||||
|
, m_isPaused(false)
|
||||||
|
, m_minLevel(Debug)
|
||||||
|
, m_totalLogCount(0)
|
||||||
|
, m_maxLogLines(MAX_LOG_LINES)
|
||||||
|
, m_statusUpdateTimer(nullptr)
|
||||||
|
{
|
||||||
|
// 初始化日志计数器
|
||||||
|
for (int i = 0; i < 5; ++i) {
|
||||||
|
m_logCounts[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
setupUI();
|
||||||
|
setupStyle();
|
||||||
|
connectSignals();
|
||||||
|
|
||||||
|
// 连接到SystemLogger的信号
|
||||||
|
connect(SystemLogger::getInstance(), &SystemLogger::logAdded,
|
||||||
|
this, [this](SystemLogger::LogLevel level, const QString &message) {
|
||||||
|
addLog(static_cast<LogLevel>(level), message);
|
||||||
|
});
|
||||||
|
|
||||||
|
qDebug() << "SystemLogPanel initialized successfully";
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemLogPanel::~SystemLogPanel()
|
||||||
|
{
|
||||||
|
if (m_statusUpdateTimer) {
|
||||||
|
m_statusUpdateTimer->stop();
|
||||||
|
}
|
||||||
|
qDebug() << "SystemLogPanel destroyed";
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogPanel::setupUI()
|
||||||
|
{
|
||||||
|
// 创建主布局
|
||||||
|
m_mainLayout = new QVBoxLayout(this);
|
||||||
|
m_mainLayout->setSpacing(4);
|
||||||
|
m_mainLayout->setContentsMargins(8, 8, 8, 10);
|
||||||
|
|
||||||
|
// 创建标题标签
|
||||||
|
m_titleLabel = new QLabel("🖥️ 系统日志", this);
|
||||||
|
m_titleLabel->setMinimumHeight(25);
|
||||||
|
m_titleLabel->setAlignment(Qt::AlignCenter);
|
||||||
|
|
||||||
|
// 创建控制按钮布局
|
||||||
|
m_controlLayout = new QHBoxLayout();
|
||||||
|
m_controlLayout->setSpacing(4);
|
||||||
|
|
||||||
|
// 创建控制按钮
|
||||||
|
m_clearButton = new QPushButton("清空", this);
|
||||||
|
m_clearButton->setMinimumSize(68, 30);
|
||||||
|
m_clearButton->setMaximumSize(68, 30);
|
||||||
|
|
||||||
|
m_pauseButton = new QPushButton("暂停", this);
|
||||||
|
m_pauseButton->setMinimumSize(68, 30);
|
||||||
|
m_pauseButton->setMaximumSize(68, 30);
|
||||||
|
|
||||||
|
// 创建级别过滤器
|
||||||
|
m_levelFilter = new QComboBox(this);
|
||||||
|
m_levelFilter->addItem("全部", static_cast<int>(Debug));
|
||||||
|
m_levelFilter->addItem("信息+", static_cast<int>(Info));
|
||||||
|
m_levelFilter->addItem("警告+", static_cast<int>(Warning));
|
||||||
|
m_levelFilter->addItem("错误+", static_cast<int>(Error));
|
||||||
|
m_levelFilter->addItem("成功", static_cast<int>(Success));
|
||||||
|
m_levelFilter->setMinimumSize(88, 30);
|
||||||
|
m_levelFilter->setMaximumSize(88, 30);
|
||||||
|
|
||||||
|
// 添加控制组件到布局
|
||||||
|
m_controlLayout->addWidget(m_clearButton);
|
||||||
|
m_controlLayout->addWidget(m_pauseButton);
|
||||||
|
m_controlLayout->addStretch();
|
||||||
|
m_controlLayout->addWidget(m_levelFilter);
|
||||||
|
|
||||||
|
// 创建日志显示文本框
|
||||||
|
m_logTextEdit = new QTextEdit(this);
|
||||||
|
m_logTextEdit->setReadOnly(true);
|
||||||
|
m_logTextEdit->setMinimumHeight(250);
|
||||||
|
m_logTextEdit->setMaximumHeight(350);
|
||||||
|
m_logTextEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||||
|
m_logTextEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||||
|
|
||||||
|
// 创建状态信息标签
|
||||||
|
m_statusLabel = new QLabel("就绪", this);
|
||||||
|
m_statusLabel->setMinimumHeight(26);
|
||||||
|
m_statusLabel->setMaximumHeight(28);
|
||||||
|
m_statusLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||||
|
|
||||||
|
// 创建状态布局
|
||||||
|
m_statusLayout = new QHBoxLayout();
|
||||||
|
m_statusLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
m_statusLayout->addWidget(m_statusLabel);
|
||||||
|
m_statusLayout->addStretch();
|
||||||
|
|
||||||
|
// 添加所有组件到主布局
|
||||||
|
m_mainLayout->addWidget(m_titleLabel);
|
||||||
|
m_mainLayout->addLayout(m_controlLayout);
|
||||||
|
m_mainLayout->addWidget(m_logTextEdit);
|
||||||
|
m_mainLayout->addLayout(m_statusLayout);
|
||||||
|
|
||||||
|
// 创建状态更新定时器
|
||||||
|
m_statusUpdateTimer = new QTimer(this);
|
||||||
|
m_statusUpdateTimer->setInterval(STATUS_UPDATE_INTERVAL);
|
||||||
|
m_statusUpdateTimer->start();
|
||||||
|
|
||||||
|
qDebug() << "SystemLogPanel UI setup completed";
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogPanel::setupStyle()
|
||||||
|
{
|
||||||
|
// 主面板样式
|
||||||
|
setStyleSheet(
|
||||||
|
"SystemLogPanel {"
|
||||||
|
" background-color: rgba(25, 35, 45, 0.95);"
|
||||||
|
" border: 2px solid rgba(82, 194, 242, 0.4);"
|
||||||
|
" border-radius: 8px;"
|
||||||
|
" padding: 4px;"
|
||||||
|
"}"
|
||||||
|
);
|
||||||
|
|
||||||
|
// 标题样式
|
||||||
|
m_titleLabel->setStyleSheet(
|
||||||
|
"QLabel {"
|
||||||
|
" color: rgb(82, 194, 242);"
|
||||||
|
" font-size: 14px;"
|
||||||
|
" font-weight: bold;"
|
||||||
|
" padding: 4px 8px;"
|
||||||
|
" background: qlineargradient(x1:0, y1:0, x2:1, y2:1,"
|
||||||
|
" stop:0 rgba(82, 194, 242, 0.2),"
|
||||||
|
" stop:1 rgba(45, 120, 180, 0.2));"
|
||||||
|
" border: 1px solid rgba(82, 194, 242, 0.5);"
|
||||||
|
" border-radius: 4px;"
|
||||||
|
"}"
|
||||||
|
);
|
||||||
|
|
||||||
|
// 按钮通用样式
|
||||||
|
QString buttonStyle =
|
||||||
|
"QPushButton {"
|
||||||
|
" background: qlineargradient(x1:0, y1:0, x2:0, y2:1,"
|
||||||
|
" stop:0 rgba(45, 65, 95, 0.8),"
|
||||||
|
" stop:1 rgba(25, 40, 65, 0.8));"
|
||||||
|
" color: rgb(220, 230, 242);"
|
||||||
|
" border: 1px solid rgba(82, 194, 242, 0.5);"
|
||||||
|
" border-radius: 4px;"
|
||||||
|
" font-size: 12px;"
|
||||||
|
" font-weight: bold;"
|
||||||
|
" padding: 3px 8px;"
|
||||||
|
"}"
|
||||||
|
"QPushButton:hover {"
|
||||||
|
" background: qlineargradient(x1:0, y1:0, x2:0, y2:1,"
|
||||||
|
" stop:0 rgba(82, 194, 242, 0.6),"
|
||||||
|
" stop:1 rgba(45, 120, 180, 0.6));"
|
||||||
|
" border: 1px solid rgba(82, 194, 242, 0.8);"
|
||||||
|
"}"
|
||||||
|
"QPushButton:pressed {"
|
||||||
|
" background: qlineargradient(x1:0, y1:0, x2:0, y2:1,"
|
||||||
|
" stop:0 rgba(82, 194, 242, 0.8),"
|
||||||
|
" stop:1 rgba(45, 120, 180, 0.8));"
|
||||||
|
"}";
|
||||||
|
|
||||||
|
m_clearButton->setStyleSheet(buttonStyle);
|
||||||
|
m_pauseButton->setStyleSheet(buttonStyle);
|
||||||
|
|
||||||
|
// 下拉框样式
|
||||||
|
m_levelFilter->setStyleSheet(
|
||||||
|
"QComboBox {"
|
||||||
|
" background: rgba(25, 40, 65, 0.8);"
|
||||||
|
" color: rgb(220, 230, 242);"
|
||||||
|
" border: 1px solid rgba(82, 194, 242, 0.5);"
|
||||||
|
" border-radius: 4px;"
|
||||||
|
" padding: 3px 8px;"
|
||||||
|
" font-size: 12px;"
|
||||||
|
" font-weight: bold;"
|
||||||
|
"}"
|
||||||
|
"QComboBox::drop-down {"
|
||||||
|
" subcontrol-origin: padding;"
|
||||||
|
" subcontrol-position: top right;"
|
||||||
|
" width: 15px;"
|
||||||
|
" border-left: 1px solid rgba(82, 194, 242, 0.5);"
|
||||||
|
"}"
|
||||||
|
"QComboBox::down-arrow {"
|
||||||
|
" width: 8px;"
|
||||||
|
" height: 8px;"
|
||||||
|
"}"
|
||||||
|
"QComboBox QAbstractItemView {"
|
||||||
|
" background-color: rgba(25, 40, 65, 0.95);"
|
||||||
|
" color: rgb(220, 230, 242);"
|
||||||
|
" border: 1px solid rgba(82, 194, 242, 0.5);"
|
||||||
|
" border-radius: 4px;"
|
||||||
|
" selection-background-color: rgba(82, 194, 242, 0.3);"
|
||||||
|
"}"
|
||||||
|
);
|
||||||
|
|
||||||
|
// 文本框样式
|
||||||
|
m_logTextEdit->setStyleSheet(
|
||||||
|
"QTextEdit {"
|
||||||
|
" background-color: rgba(15, 22, 32, 0.9);"
|
||||||
|
" color: rgb(220, 230, 242);"
|
||||||
|
" border: 1px solid rgba(82, 194, 242, 0.4);"
|
||||||
|
" border-radius: 6px;"
|
||||||
|
" padding: 6px;"
|
||||||
|
" font-family: 'Consolas', 'Monaco', monospace;"
|
||||||
|
" font-size: 13px;"
|
||||||
|
" line-height: 1.4;"
|
||||||
|
" selection-background-color: rgba(82, 194, 242, 0.3);"
|
||||||
|
"}"
|
||||||
|
"QScrollBar:vertical {"
|
||||||
|
" background-color: rgba(30, 44, 62, 0.8);"
|
||||||
|
" width: 10px;"
|
||||||
|
" border-radius: 5px;"
|
||||||
|
"}"
|
||||||
|
"QScrollBar::handle:vertical {"
|
||||||
|
" background-color: rgba(82, 194, 242, 0.6);"
|
||||||
|
" border-radius: 5px;"
|
||||||
|
" min-height: 20px;"
|
||||||
|
"}"
|
||||||
|
"QScrollBar::handle:vertical:hover {"
|
||||||
|
" background-color: rgba(82, 194, 242, 0.8);"
|
||||||
|
"}"
|
||||||
|
);
|
||||||
|
|
||||||
|
// 状态标签样式
|
||||||
|
m_statusLabel->setStyleSheet(
|
||||||
|
"QLabel {"
|
||||||
|
" color: rgb(150, 180, 210);"
|
||||||
|
" font-size: 12px;"
|
||||||
|
" font-weight: normal;"
|
||||||
|
" padding: 3px 6px;"
|
||||||
|
" background: transparent;"
|
||||||
|
"}"
|
||||||
|
);
|
||||||
|
|
||||||
|
qDebug() << "SystemLogPanel styles applied";
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogPanel::connectSignals()
|
||||||
|
{
|
||||||
|
// 连接按钮信号
|
||||||
|
connect(m_clearButton, &QPushButton::clicked,
|
||||||
|
this, &SystemLogPanel::onClearButtonClicked);
|
||||||
|
connect(m_pauseButton, &QPushButton::clicked,
|
||||||
|
this, &SystemLogPanel::onPauseButtonClicked);
|
||||||
|
|
||||||
|
// 连接下拉框信号
|
||||||
|
connect(m_levelFilter, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||||
|
this, &SystemLogPanel::onLevelFilterChanged);
|
||||||
|
|
||||||
|
// 连接定时器信号
|
||||||
|
connect(m_statusUpdateTimer, &QTimer::timeout,
|
||||||
|
this, &SystemLogPanel::updateStatusInfo);
|
||||||
|
|
||||||
|
qDebug() << "SystemLogPanel signals connected";
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogPanel::addLog(LogLevel level, const QString &message)
|
||||||
|
{
|
||||||
|
// 如果暂停则不添加日志
|
||||||
|
if (m_isPaused) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查级别过滤
|
||||||
|
if (level < m_minLevel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新计数器
|
||||||
|
if (level >= 0 && level < 5) {
|
||||||
|
m_logCounts[level]++;
|
||||||
|
}
|
||||||
|
m_totalLogCount++;
|
||||||
|
|
||||||
|
// 格式化并添加日志条目
|
||||||
|
QString formattedEntry = formatLogEntry(level, message);
|
||||||
|
m_logTextEdit->append(formattedEntry);
|
||||||
|
|
||||||
|
// 限制日志行数
|
||||||
|
limitLogLines();
|
||||||
|
|
||||||
|
// 自动滚动到底部
|
||||||
|
scrollToBottom();
|
||||||
|
|
||||||
|
qDebug() << QString("Log added: [%1] %2").arg(getLevelName(level)).arg(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogPanel::clearLogs()
|
||||||
|
{
|
||||||
|
m_logTextEdit->clear();
|
||||||
|
|
||||||
|
// 重置计数器
|
||||||
|
for (int i = 0; i < 5; ++i) {
|
||||||
|
m_logCounts[i] = 0;
|
||||||
|
}
|
||||||
|
m_totalLogCount = 0;
|
||||||
|
|
||||||
|
// 更新状态信息
|
||||||
|
updateStatusInfo();
|
||||||
|
|
||||||
|
qDebug() << "System logs cleared";
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogPanel::pauseLogging()
|
||||||
|
{
|
||||||
|
m_isPaused = true;
|
||||||
|
m_pauseButton->setText("恢复");
|
||||||
|
updateStatusInfo();
|
||||||
|
qDebug() << "Logging paused";
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogPanel::resumeLogging()
|
||||||
|
{
|
||||||
|
m_isPaused = false;
|
||||||
|
m_pauseButton->setText("暂停");
|
||||||
|
updateStatusInfo();
|
||||||
|
qDebug() << "Logging resumed";
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogPanel::setLogLevelFilter(LogLevel minLevel)
|
||||||
|
{
|
||||||
|
m_minLevel = minLevel;
|
||||||
|
// 更新下拉框选择
|
||||||
|
for (int i = 0; i < m_levelFilter->count(); ++i) {
|
||||||
|
if (m_levelFilter->itemData(i).toInt() == static_cast<int>(minLevel)) {
|
||||||
|
m_levelFilter->setCurrentIndex(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qDebug() << "Log level filter set to:" << getLevelName(minLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogPanel::onClearButtonClicked()
|
||||||
|
{
|
||||||
|
clearLogs();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogPanel::onPauseButtonClicked()
|
||||||
|
{
|
||||||
|
if (m_isPaused) {
|
||||||
|
resumeLogging();
|
||||||
|
} else {
|
||||||
|
pauseLogging();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogPanel::onLevelFilterChanged(int index)
|
||||||
|
{
|
||||||
|
if (index >= 0 && index < m_levelFilter->count()) {
|
||||||
|
LogLevel newLevel = static_cast<LogLevel>(m_levelFilter->itemData(index).toInt());
|
||||||
|
m_minLevel = newLevel;
|
||||||
|
qDebug() << "Log level filter changed to:" << getLevelName(newLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogPanel::updateStatusInfo()
|
||||||
|
{
|
||||||
|
QString statusText = QString("总计: %1 | 错误: %2 | 警告: %3")
|
||||||
|
.arg(m_totalLogCount)
|
||||||
|
.arg(m_logCounts[Error])
|
||||||
|
.arg(m_logCounts[Warning]);
|
||||||
|
|
||||||
|
if (m_isPaused) {
|
||||||
|
statusText += " | 已暂停";
|
||||||
|
} else {
|
||||||
|
statusText += " | 运行中";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_statusLabel->setText(statusText);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SystemLogPanel::formatLogEntry(LogLevel level, const QString &message)
|
||||||
|
{
|
||||||
|
QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
|
||||||
|
QString levelIcon = getLevelIcon(level);
|
||||||
|
QString levelColor = getLevelColor(level);
|
||||||
|
|
||||||
|
return QString("<span style='color: %1'>[%2] %3 %4</span>")
|
||||||
|
.arg(levelColor)
|
||||||
|
.arg(timestamp)
|
||||||
|
.arg(levelIcon)
|
||||||
|
.arg(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SystemLogPanel::getLevelIcon(LogLevel level)
|
||||||
|
{
|
||||||
|
switch (level) {
|
||||||
|
case Debug: return "🔍";
|
||||||
|
case Info: return "🔵";
|
||||||
|
case Warning: return "🟡";
|
||||||
|
case Error: return "🔴";
|
||||||
|
case Success: return "🟢";
|
||||||
|
default: return "⚪";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SystemLogPanel::getLevelColor(LogLevel level)
|
||||||
|
{
|
||||||
|
switch (level) {
|
||||||
|
case Debug: return "#9E9E9E";
|
||||||
|
case Info: return "#52C2F2";
|
||||||
|
case Warning: return "#FFD700";
|
||||||
|
case Error: return "#FF4444";
|
||||||
|
case Success: return "#00FF7F";
|
||||||
|
default: return "#FFFFFF";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SystemLogPanel::getLevelName(LogLevel level)
|
||||||
|
{
|
||||||
|
switch (level) {
|
||||||
|
case Debug: return "Debug";
|
||||||
|
case Info: return "Info";
|
||||||
|
case Warning: return "Warning";
|
||||||
|
case Error: return "Error";
|
||||||
|
case Success: return "Success";
|
||||||
|
default: return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogPanel::limitLogLines()
|
||||||
|
{
|
||||||
|
// 获取文档和光标
|
||||||
|
QTextDocument *document = m_logTextEdit->document();
|
||||||
|
int blockCount = document->blockCount();
|
||||||
|
|
||||||
|
// 如果超过最大行数,删除最旧的行
|
||||||
|
if (blockCount > m_maxLogLines) {
|
||||||
|
QTextCursor cursor(document);
|
||||||
|
cursor.movePosition(QTextCursor::Start);
|
||||||
|
cursor.movePosition(QTextCursor::Down, QTextCursor::KeepAnchor,
|
||||||
|
blockCount - m_maxLogLines);
|
||||||
|
cursor.removeSelectedText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogPanel::scrollToBottom()
|
||||||
|
{
|
||||||
|
QScrollBar *scrollBar = m_logTextEdit->verticalScrollBar();
|
||||||
|
scrollBar->setValue(scrollBar->maximum());
|
||||||
|
}
|
@ -0,0 +1,158 @@
|
|||||||
|
/**
|
||||||
|
* @file SystemLogger.cpp
|
||||||
|
* @brief 系统日志管理器单例类实现
|
||||||
|
* @author Qt UI Developer Expert
|
||||||
|
* @date 2024-12-21
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "utils/SystemLogger.h"
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QMutexLocker>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
// 静态成员初始化
|
||||||
|
SystemLogger* SystemLogger::s_instance = nullptr;
|
||||||
|
QMutex SystemLogger::s_mutex;
|
||||||
|
|
||||||
|
SystemLogger::SystemLogger(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_consoleOutputEnabled(true)
|
||||||
|
{
|
||||||
|
qDebug() << "SystemLogger instance created";
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemLogger::~SystemLogger()
|
||||||
|
{
|
||||||
|
qDebug() << "SystemLogger instance destroyed";
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemLogger* SystemLogger::getInstance()
|
||||||
|
{
|
||||||
|
// 双重检查锁定模式确保线程安全
|
||||||
|
if (s_instance == nullptr) {
|
||||||
|
QMutexLocker locker(&s_mutex);
|
||||||
|
if (s_instance == nullptr) {
|
||||||
|
s_instance = new SystemLogger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogger::destroyInstance()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&s_mutex);
|
||||||
|
if (s_instance != nullptr) {
|
||||||
|
delete s_instance;
|
||||||
|
s_instance = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogger::logDebug(const QString &message)
|
||||||
|
{
|
||||||
|
log(Debug, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogger::logInfo(const QString &message)
|
||||||
|
{
|
||||||
|
log(Info, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogger::logWarning(const QString &message)
|
||||||
|
{
|
||||||
|
log(Warning, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogger::logError(const QString &message)
|
||||||
|
{
|
||||||
|
log(Error, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogger::logSuccess(const QString &message)
|
||||||
|
{
|
||||||
|
log(Success, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogger::log(LogLevel level, const QString &message)
|
||||||
|
{
|
||||||
|
logInternal(level, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogger::setConsoleOutputEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_logMutex);
|
||||||
|
m_consoleOutputEnabled = enabled;
|
||||||
|
|
||||||
|
QString statusMsg = enabled ? "Console output enabled" : "Console output disabled";
|
||||||
|
qDebug() << "SystemLogger:" << statusMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SystemLogger::getLevelString(LogLevel level)
|
||||||
|
{
|
||||||
|
switch (level) {
|
||||||
|
case Debug: return "DEBUG";
|
||||||
|
case Info: return "INFO";
|
||||||
|
case Warning: return "WARNING";
|
||||||
|
case Error: return "ERROR";
|
||||||
|
case Success: return "SUCCESS";
|
||||||
|
default: return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogger::logInternal(LogLevel level, const QString &message)
|
||||||
|
{
|
||||||
|
// 线程安全保护
|
||||||
|
QMutexLocker locker(&m_logMutex);
|
||||||
|
|
||||||
|
// 输出到控制台(如果启用)
|
||||||
|
if (m_consoleOutputEnabled) {
|
||||||
|
outputToConsole(level, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发出信号通知UI组件
|
||||||
|
emit logAdded(level, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemLogger::outputToConsole(LogLevel level, const QString &message)
|
||||||
|
{
|
||||||
|
QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");
|
||||||
|
QString levelStr = getLevelString(level);
|
||||||
|
QString logLine = QString("[%1] [%2] %3").arg(timestamp, levelStr, message);
|
||||||
|
|
||||||
|
// 根据日志级别选择输出流
|
||||||
|
switch (level) {
|
||||||
|
case Error:
|
||||||
|
// 错误输出到标准错误流
|
||||||
|
std::cerr << logLine.toStdString() << std::endl;
|
||||||
|
break;
|
||||||
|
case Warning:
|
||||||
|
// 警告也输出到标准错误流
|
||||||
|
std::cerr << logLine.toStdString() << std::endl;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// 其他级别输出到标准输出流
|
||||||
|
std::cout << logLine.toStdString() << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 同时也输出到Qt的调试系统
|
||||||
|
switch (level) {
|
||||||
|
case Debug:
|
||||||
|
qDebug().noquote() << logLine;
|
||||||
|
break;
|
||||||
|
case Info:
|
||||||
|
qInfo().noquote() << logLine;
|
||||||
|
break;
|
||||||
|
case Warning:
|
||||||
|
qWarning().noquote() << logLine;
|
||||||
|
break;
|
||||||
|
case Error:
|
||||||
|
qCritical().noquote() << logLine;
|
||||||
|
break;
|
||||||
|
case Success:
|
||||||
|
qInfo().noquote() << logLine; // 成功信息使用qInfo输出
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue