14 searchLineEdit =
new QLineEdit(
this);
15 searchLineEdit->setPlaceholderText(
"Filter log lines (case insensitive)...");
16 searchLineEdit->setClearButtonEnabled(
true);
19 clearButton =
new QToolButton(
this);
20 clearButton->setIcon(style()->standardIcon(QStyle::SP_DialogResetButton));
21 clearButton->setToolTip(
"Clear Log");
22 clearButton->setText(
"Clear");
23 clearButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
24 clearButton->setEnabled(
true);
26 saveButton =
new QToolButton(
this);
27 saveButton->setIcon(style()->standardIcon(QStyle::SP_DialogSaveButton));
28 saveButton->setToolTip(
"Save Log to File");
29 saveButton->setEnabled(
true);
33 auto* topBarLayout =
new QHBoxLayout;
34 topBarLayout->addWidget(searchLineEdit);
35 topBarLayout->addWidget(clearButton);
36 topBarLayout->addWidget(saveButton);
37 topBarLayout->setSpacing(5);
40 logTextEdit =
new QTextEdit(
this);
41 logTextEdit->setReadOnly(
true);
42 logTextEdit->setMinimumHeight(200);
43 logTextEdit->setMinimumWidth(400);
51 auto* layout =
new QVBoxLayout(
this);
52 layout->addLayout(topBarLayout);
53 layout->addWidget(logTextEdit, 1);
57 connect(searchLineEdit, &QLineEdit::textChanged,
this, &GBoard::filterLog);
58 connect(clearButton, &QToolButton::clicked,
this, &GBoard::clearLog);
59 connect(saveButton, &QToolButton::clicked,
this, &GBoard::saveLog);
61 log->info(1,
"GBoard initialized");
65 if (!logTextEdit)
return;
69 if (QThread::currentThread() != logTextEdit->thread()) {
70 QMetaObject::invokeMethod(
this,
"appendLog", Qt::QueuedConnection, Q_ARG(QString, htmlFragment));
75 QTextDocument* doc = logTextEdit->document();
76 QTextCursor cursor = logTextEdit->textCursor();
79 bool isAtEnd = (cursor.position() == doc->characterCount() - 1) ||
80 (logTextEdit->verticalScrollBar()->value() == logTextEdit->verticalScrollBar()->maximum());
84 cursor.movePosition(QTextCursor::End);
85 logTextEdit->setTextCursor(cursor);
91 logTextEdit->insertHtml(htmlFragment);
97 logTextEdit->setTextCursor(cursor);
101 QTextBlock targetBlock = cursor.block().previous();
102 if (!targetBlock.isValid()) {
103 targetBlock = doc->firstBlock();
106 if (targetBlock.isValid() && !currentFilterText.isEmpty()) {
107 bool matches = targetBlock.text().indexOf(currentFilterText, 0, Qt::CaseInsensitive) >= 0;
108 targetBlock.setVisible(matches);
110 else if (targetBlock.isValid()) {
112 targetBlock.setVisible(
true);
116 if (isAtEnd) { logTextEdit->verticalScrollBar()->setValue(logTextEdit->verticalScrollBar()->maximum()); }
120void GBoard::filterLog(
const QString& searchText) {
121 if (!logTextEdit)
return;
123 currentFilterText = searchText.trimmed();
124 QTextDocument* document = logTextEdit->document();
127 Qt::CaseSensitivity cs = Qt::CaseInsensitive;
129 QTextCursor hideCursor(document);
130 hideCursor.beginEditBlock();
132 for (QTextBlock block = document->begin(); block.isValid(); block = block.next()) {
133 QString blockText = block.text();
134 bool contains = (block.text().indexOf(currentFilterText, 0, cs) >= 0);
135 bool matches = currentFilterText.isEmpty() || contains;
136 block.setVisible(matches);
139 hideCursor.endEditBlock();
142 logTextEdit->viewport()->update();
150void GBoard::clearLog() {
152 logTextEdit->clear();
155 log->info(1,
"Log cleared by user.");
160void GBoard::saveLog() {
161 if (!logTextEdit)
return;
163 QString defaultFileName =
"gboard_log.log";
164 QString fileName = QFileDialog::getSaveFileName(
this,
167 tr(
"Log Files (*.log);;Text Files (*.txt);;All Files (*)"));
169 if (fileName.isEmpty()) {
173 QFile file(fileName);
174 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
175 QMessageBox::warning(
this, tr(
"Save Log Error"),
176 tr(
"Could not open file %1 for writing:\n%2.")
177 .arg(QDir::toNativeSeparators(fileName), file.errorString()));
178 log->warning(
"Failed to save log to ", fileName.toStdString(),
". Error: ", file.errorString().toStdString());
182 QTextStream out(&file);
185 out << logTextEdit->toPlainText();
188 log->info(
"Log saved successfully to ", fileName.toStdString());
GBoard(const std::shared_ptr< GOptions > &gopt, QWidget *parent=nullptr)
Constructs a new GBoard widget.
void appendLog(const QString &text)
Appends a log message to the log tab.
constexpr const char * GBOARD_LOGGER