7#include <QRegularExpression>
15 searchLineEdit =
new QLineEdit(
this);
16 searchLineEdit->setObjectName(
"searchLineEdit");
17 searchLineEdit->setPlaceholderText(
"Filter log lines (case insensitive)...");
18 searchLineEdit->setClearButtonEnabled(
true);
20 clearButton =
new QToolButton(
this);
21 clearButton->setObjectName(
"clearButton");
22 clearButton->setIcon(style()->standardIcon(QStyle::SP_DialogResetButton));
23 clearButton->setToolTip(
"Clear Log");
24 clearButton->setText(
"Clear");
26 clearButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
27 clearButton->setEnabled(
true);
29 saveButton =
new QToolButton(
this);
30 saveButton->setIcon(style()->standardIcon(QStyle::SP_DialogSaveButton));
31 saveButton->setToolTip(
"Save Log to File");
32 saveButton->setEnabled(
true);
36 auto* topBarLayout =
new QHBoxLayout;
37 topBarLayout->addWidget(searchLineEdit);
38 topBarLayout->addWidget(clearButton);
39 topBarLayout->addWidget(saveButton);
40 topBarLayout->setSpacing(5);
44 logTextEdit =
new QTextEdit(
this);
45 logTextEdit->setAcceptRichText(
true);
46 logTextEdit->setReadOnly(
true);
47 logTextEdit->setMinimumHeight(200);
48 logTextEdit->setMinimumWidth(400);
53 "QWidget { background-color: #0b0e12; color: #e6e6e6; }"
54 "QTextEdit { background-color: #0f1115; color: #e6e6e6; }"
56 "QLineEdit#searchLineEdit { background-color: #ffffff; color: #000000; }"
57 "QToolButton#clearButton { background-color: #f0f0f0; color: #000000; }");
59 auto* layout =
new QVBoxLayout(
this);
60 layout->addLayout(topBarLayout);
61 layout->addWidget(logTextEdit, 1);
66 connect(searchLineEdit, &QLineEdit::textChanged,
this, &GBoard::filterLog);
67 connect(clearButton, &QToolButton::clicked,
this, &GBoard::clearLog);
68 connect(saveButton, &QToolButton::clicked,
this, &GBoard::saveLog);
70 log->
info(1,
"GBoard initialized");
75 if (htmlFragment.trimmed().isEmpty()) {
return; }
79 fullLogLines.append(htmlFragment);
85void GBoard::updateDisplay() {
87 if (!logTextEdit)
return;
91 if (QThread::currentThread() != logTextEdit->thread()) {
92 QMetaObject::invokeMethod(
this,
"updateDisplay", Qt::QueuedConnection);
98 const bool filtering = !currentFilterText.isEmpty();
99 Qt::CaseSensitivity cs = Qt::CaseInsensitive;
102 for (
const QString& line : fullLogLines) {
105 if (filtering) { matches = (line.indexOf(currentFilterText, 0, cs) >= 0); }
107 if (matches) { logTextEdit->append(line); }
111 logTextEdit->verticalScrollBar()->setValue(logTextEdit->verticalScrollBar()->maximum());
114void GBoard::filterLog(
const QString& searchText) {
117 currentFilterText = searchText.trimmed();
121void GBoard::clearLog() {
124 fullLogLines.clear();
126 log->
info(1,
"Log cleared by user.");
131void GBoard::saveLog() {
133 if (!logTextEdit)
return;
135 QString defaultFileName =
"gboard_log.log";
136 QString fileName = QFileDialog::getSaveFileName(
this,
139 tr(
"Log Files (*.log);;Text Files (*.txt);;All Files (*)"));
141 if (fileName.isEmpty()) {
145 QFile file(fileName);
146 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
147 QMessageBox::warning(
this, tr(
"Save Log Error"),
148 tr(
"Could not open file %1 for writing:\n%2.")
149 .arg(QDir::toNativeSeparators(fileName), file.errorString()));
150 log->
warning(
"Failed to save log to ", fileName.toStdString(),
". Error: ", file.errorString().toStdString());
154 QTextStream out(&file);
157 out << logTextEdit->toPlainText();
160 log->
info(
"Log saved successfully to ", fileName.toStdString());
std::shared_ptr< GLogger > log
GBoard(const std::shared_ptr< GOptions > &gopt, QWidget *parent=nullptr)
Constructs a new GBoard widget.
void appendLog(const QString &text)
Appends a log line to the internal history and updates the display.
void warning(Args &&... args) const
void info(int level, Args &&... args) const
constexpr const char * GBOARD_LOGGER