#include "qlogviewer.h" #include #include #include #include #include QLogViewer::QLogViewer(QWidget *parent) : QWidget(parent) { // 创建主布局 QVBoxLayout* layout = new QVBoxLayout(this); layout->setContentsMargins(5, 5, 5, 5); // 创建工具栏 QHBoxLayout* toolbarLayout = new QHBoxLayout; toolbarLayout->setSpacing(10); // 日志级别过滤器 QLabel* levelLabel = new QLabel("Log Level:"); levelLabel->setStyleSheet("color: #000;"); levelCombo = new QComboBox; levelCombo->setStyleSheet("background-color: #333; color: #EEE;"); levelCombo->addItem("All", QVariant(-1)); levelCombo->addItem("DEBUG", QLogManager::LogLevel::SQ_DEBUG); levelCombo->addItem("INFO", QLogManager::LogLevel::SQ_INFO); levelCombo->addItem("WARNING", QLogManager::LogLevel::SQ_WARNING); levelCombo->addItem("ERROR", QLogManager::LogLevel::SQ_ERROR); levelCombo->addItem("FATAL", QLogManager::LogLevel::SQ_FATAL); levelCombo->setCurrentIndex(2); // 默认显示INFO及以上 // 搜索框 QLabel* searchLabel = new QLabel("Search:"); searchLabel->setStyleSheet("color: #000;"); searchEdit = new QLineEdit; searchEdit->setStyleSheet("background-color: #333; color: #EEE;"); searchEdit->setPlaceholderText("Filter logs..."); // 控制按钮 clearBtn = new QPushButton("Clear Logs"); clearBtn->setStyleSheet("background-color: #444; color: #EEE;"); saveBtn = new QPushButton("Save Logs"); saveBtn->setStyleSheet("background-color: #444; color: #EEE;"); //// 添加工具栏组件 //toolbarLayout->addWidget(levelLabel); //toolbarLayout->addWidget(levelCombo); //toolbarLayout->addSpacing(10); //toolbarLayout->addWidget(searchLabel); //toolbarLayout->addWidget(searchEdit); //toolbarLayout->addStretch(); //toolbarLayout->addWidget(clearBtn); //toolbarLayout->addWidget(saveBtn); // 日志显示区域 logText = new QTextEdit; logText->setReadOnly(true); logText->setFontFamily("Consolas"); logText->setFontPointSize(9); logText->setStyleSheet(R"( QTextEdit { background-color: #222; color: #CCC; border: 1px solid #444; border-radius: 2px; } )"); // 连接信号 connect(levelCombo, QOverload::of(&QComboBox::currentIndexChanged), this, &QLogViewer::filterLogs); connect(searchEdit, &QLineEdit::textChanged, this, &QLogViewer::filterLogs); connect(clearBtn, &QPushButton::clicked, this, [this](){ logCache.clear(); logText->clear(); }); connect(saveBtn, &QPushButton::clicked, this, &QLogViewer::saveLogs); // 添加到主布局 layout->addLayout(toolbarLayout); layout->addWidget(logText); // 连接到日志管理器 QLogManager* logManager = QLogManager::getInstance(); connect(logManager, &QLogManager::newLog, this, &QLogViewer::appendLog); } void QLogViewer::appendLog(QLogManager::LogLevel level, const QString& logLine) { // 添加到缓存 logCache.append(qMakePair(level, logLine)); // 应用当前过滤 applyFilter(); // 自动滚动到底部 QScrollBar* scrollbar = logText->verticalScrollBar(); scrollbar->setValue(scrollbar->maximum()); } void QLogViewer::filterLogs() { // 保存滚动位置 QScrollBar* scrollbar = logText->verticalScrollBar(); int scrollPos = scrollbar->value(); double scrollRatio = scrollPos / (double)scrollbar->maximum(); // 重新应用过滤 logText->clear(); applyFilter(); // 恢复滚动位置 if (scrollbar->maximum() > 0) { scrollbar->setValue(scrollbar->maximum() * scrollRatio); } } void QLogViewer::applyFilter() { int levelFilter = levelCombo->currentData().toInt(); QString searchText = searchEdit->text().toLower(); // 记录当前选中的文本,显示指定等级 QString selectedText = logText->textCursor().selectedText(); // 清空原来数据 logText->clear(); // 过滤并显示日志 for (const auto& log : logCache) { QLogManager::LogLevel level = log.first; const QString& logLine = log.second; // 过滤日志级别,过滤掉低于指定等级的缺陷 if (levelFilter != -1 && (int)level < levelFilter) { continue; } // 过滤搜索文本 if (!searchText.isEmpty() && !logLine.toLower().contains(searchText)) { continue; } // 格式化并添加日志行 QString formattedLog; switch (level) { case QLogManager::LogLevel::SQ_DEBUG: formattedLog = "" + logLine + ""; break; case QLogManager::LogLevel::SQ_INFO: formattedLog = "" + logLine + ""; break; case QLogManager::LogLevel::SQ_WARNING: formattedLog = "" + logLine + ""; break; case QLogManager::LogLevel::SQ_ERROR: formattedLog = "" + logLine + ""; break; case QLogManager::LogLevel::SQ_FATAL: formattedLog = "" + logLine + ""; break; } logText->append(formattedLog); } // 恢复选中的文本(如果可能) if (!selectedText.isEmpty()) { QTextCursor cursor = logText->textCursor(); cursor.movePosition(QTextCursor::Start); if (cursor.document()->find(selectedText, cursor).isNull()) { // 如果选中文本不再存在,清除选中 cursor.clearSelection(); logText->setTextCursor(cursor); } } } void QLogViewer::saveLogs() { // 弹出保存对话框 QString fileName = QFileDialog::getSaveFileName( this, "Save Logs", QString("quant_logs_%1.txt") .arg(QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss")), "Text Files (*.txt);;All Files (*)" ); if (fileName.isEmpty()) { return; } // 写入文件 QFile file(fileName); if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream out(&file); // 写入文件头 out << "Quant Trading System Logs\n"; out << "Generated: " << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") << "\n"; out << "========================================\n\n"; // 写入所有日志行 for (const auto& log : logCache) { out << log.second << "\n"; } file.close(); // 记录保存事件 QLogManager::getInstance()->log( QLogManager::LogLevel::SQ_INFO, QString("Logs saved to: %1 (%2 entries)") .arg(fileName) .arg(logCache.size()) ); // 在界面显示成功消息 logText->append("Logs saved successfully"); } else { // 记录错误 QLogManager::getInstance()->log( QLogManager::LogLevel::SQ_ERROR, QString("Failed to save logs: %1").arg(file.errorString()) ); // 在界面显示错误 logText->append("Failed to save logs: " + file.errorString() + ""); } }