feat(editor): hyperlink in stack trace
This commit is contained in:
parent
1cbb349e05
commit
9ca0bb0cec
7 changed files with 157 additions and 44 deletions
|
@ -130,6 +130,12 @@ void ScriptContext::RunSleepingThreads() {
|
|||
}
|
||||
|
||||
std::string ScriptContext::RegisterScriptSource(std::shared_ptr<Script> script) {
|
||||
// If it has already been registered, reference it here
|
||||
for (auto& [id, script2] : scriptSources) {
|
||||
if (!script2.expired() && script2.lock() == script)
|
||||
return "=f" + std::to_string(id);
|
||||
}
|
||||
|
||||
int id = lastScriptSourceId++;
|
||||
scriptSources[id] = script;
|
||||
return "=f" + std::to_string(id);
|
||||
|
|
|
@ -24,14 +24,16 @@ set(PROJECT_SOURCES
|
|||
mainwindow.ui
|
||||
mainglwidget.h
|
||||
mainglwidget.cpp
|
||||
placedocument.h
|
||||
placedocument.cpp
|
||||
panes/explorerview.h
|
||||
panes/explorerview.cpp
|
||||
panes/explorermodel.h
|
||||
panes/explorermodel.cpp
|
||||
panes/propertiesview.h
|
||||
panes/propertiesview.cpp
|
||||
placedocument.h
|
||||
placedocument.cpp
|
||||
panes/outputtextview.h
|
||||
panes/outputtextview.cpp
|
||||
script/scriptdocument.h
|
||||
script/scriptdocument.cpp
|
||||
${TS_FILES}
|
||||
|
|
|
@ -5,8 +5,10 @@
|
|||
#include "objects/datamodel.h"
|
||||
#include "placedocument.h"
|
||||
#include "script/scriptdocument.h"
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <qclipboard.h>
|
||||
#include <qevent.h>
|
||||
#include <qglobal.h>
|
||||
#include <qmessagebox.h>
|
||||
#include <qmimedata.h>
|
||||
|
@ -15,6 +17,8 @@
|
|||
#include <qstylehints.h>
|
||||
#include <qmdisubwindow.h>
|
||||
#include <pugixml.hpp>
|
||||
#include <qtextcursor.h>
|
||||
#include <qtextedit.h>
|
||||
|
||||
#ifdef _NDEBUG
|
||||
#define NDEBUG
|
||||
|
@ -79,27 +83,6 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
this->close();
|
||||
});
|
||||
|
||||
// Logger
|
||||
|
||||
Logger::addLogListener(std::bind(&MainWindow::handleLog, this, std::placeholders::_1, std::placeholders::_2));
|
||||
Logger::addLogListener(std::bind(&MainWindow::handleLogTrace, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
|
||||
|
||||
QFont font("");
|
||||
font.setStyleHint(QFont::Monospace);
|
||||
ui->outputTextView->setFont(font);
|
||||
|
||||
ui->outputTextView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui->outputTextView, &QWidget::customContextMenuRequested, [&](QPoint point) {
|
||||
QMenu *menu = ui->outputTextView->createStandardContextMenu(point);
|
||||
|
||||
menu->addAction("Clear Output", [&]() {
|
||||
ui->outputTextView->clear();
|
||||
});
|
||||
|
||||
menu->exec(ui->outputTextView->mapToGlobal(point));
|
||||
delete menu;
|
||||
});
|
||||
|
||||
connectActionHandlers();
|
||||
|
||||
// Update properties
|
||||
|
@ -157,24 +140,6 @@ void MainWindow::closeEvent(QCloseEvent* evt) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::handleLog(Logger::LogLevel logLevel, std::string message) {
|
||||
if (logLevel == Logger::LogLevel::DEBUG) return;
|
||||
|
||||
if (logLevel == Logger::LogLevel::INFO)
|
||||
ui->outputTextView->appendHtml(QString("<p>%1</p>").arg(QString::fromStdString(message)));
|
||||
if (logLevel == Logger::LogLevel::TRACE)
|
||||
ui->outputTextView->appendHtml(QString("<p style=\"color:rgb(0, 127, 255);\">%1</p>").arg(QString::fromStdString(message)));
|
||||
if (logLevel == Logger::LogLevel::WARNING)
|
||||
ui->outputTextView->appendHtml(QString("<p style=\"color:rgb(255, 127, 0); font-weight: bold;\">%1</p>").arg(QString::fromStdString(message)));
|
||||
if (logLevel == Logger::LogLevel::ERROR || logLevel == Logger::LogLevel::FATAL_ERROR)
|
||||
ui->outputTextView->appendHtml(QString("<p style=\"color:rgb(255, 0, 0); font-weight: bold;\">%1</p>").arg(QString::fromStdString(message)));
|
||||
}
|
||||
|
||||
void MainWindow::handleLogTrace(std::string message, std::string source, int line, void* userData) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::connectActionHandlers() {
|
||||
// Explorer View
|
||||
|
||||
|
|
|
@ -64,8 +64,6 @@ private:
|
|||
|
||||
void updateToolbars();
|
||||
void closeEvent(QCloseEvent* evt) override;
|
||||
void handleLog(Logger::LogLevel, std::string);
|
||||
void handleLogTrace(std::string, std::string, int, void*);
|
||||
|
||||
void connectActionHandlers();
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@
|
|||
<widget class="QWidget" name="dockWidgetContents_3">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="outputTextView">
|
||||
<widget class="OutputTextView" name="outputTextView">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
|
@ -780,6 +780,11 @@
|
|||
<extends>QTreeView</extends>
|
||||
<header>panes/propertiesview.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>OutputTextView</class>
|
||||
<extends>QTextEdit</extends>
|
||||
<header>panes/outputtextview.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
|
112
editor/panes/outputtextview.cpp
Normal file
112
editor/panes/outputtextview.cpp
Normal file
|
@ -0,0 +1,112 @@
|
|||
#include "outputtextview.h"
|
||||
#include "mainwindow.h"
|
||||
#include "objects/script.h"
|
||||
#include "panes/outputtextview.h"
|
||||
#include <QEvent>
|
||||
#include <QTextEdit>
|
||||
#include <QWidget>
|
||||
#include <QMouseEvent>
|
||||
#include <qcursor.h>
|
||||
#include <qmenu.h>
|
||||
#include <qnamespace.h>
|
||||
#include <string>
|
||||
|
||||
OutputTextView::OutputTextView(QWidget* parent) : QTextEdit(parent) {
|
||||
Logger::addLogListener(std::bind(&OutputTextView::handleLog, this, std::placeholders::_1, std::placeholders::_2));
|
||||
Logger::addLogListener(std::bind(&OutputTextView::handleLogTrace, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
|
||||
ensureCursorVisible();
|
||||
|
||||
QFont font("");
|
||||
font.setStyleHint(QFont::Monospace);
|
||||
setFont(font);
|
||||
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(this, &QWidget::customContextMenuRequested, [&](QPoint point) {
|
||||
QMenu *menu = createStandardContextMenu(point);
|
||||
|
||||
menu->addAction("Clear Output", [&]() {
|
||||
clear();
|
||||
stackTraceScripts.clear();
|
||||
});
|
||||
|
||||
menu->exec(mapToGlobal(point));
|
||||
delete menu;
|
||||
});
|
||||
}
|
||||
|
||||
OutputTextView::~OutputTextView() = default;
|
||||
|
||||
void OutputTextView::handleLog(Logger::LogLevel logLevel, std::string message) {
|
||||
if (logLevel == Logger::LogLevel::DEBUG) return;
|
||||
|
||||
// Skip if trace, as that is handled by handleLogTrace
|
||||
if (logLevel == Logger::LogLevel::TRACE && !message.starts_with("Stack"))
|
||||
return;
|
||||
|
||||
// https://stackoverflow.com/a/61722734/16255372
|
||||
moveCursor(QTextCursor::MoveOperation::End);
|
||||
QTextCursor cursor = textCursor();
|
||||
QTextCharFormat format = cursor.charFormat();
|
||||
|
||||
if (logLevel == Logger::LogLevel::TRACE) {
|
||||
format.setForeground(QColor(0, 127, 255));
|
||||
} else if (logLevel == Logger::LogLevel::WARNING) {
|
||||
format.setForeground(QColor(255, 127, 0));
|
||||
format.setFontWeight(QFont::Bold); // https://forum.qt.io/post/505920
|
||||
} else if (logLevel == Logger::LogLevel::ERROR || logLevel == Logger::LogLevel::FATAL_ERROR) {
|
||||
format.setForeground(QColor(255, 0, 0));
|
||||
format.setFontWeight(QFont::Bold);
|
||||
}
|
||||
|
||||
cursor.insertText(message.c_str(), format);
|
||||
cursor.insertText("\n", QTextCharFormat());
|
||||
}
|
||||
|
||||
void OutputTextView::handleLogTrace(std::string message, std::string source, int line, void* userData) {
|
||||
std::weak_ptr<Script>* script = (std::weak_ptr<Script>*)userData;
|
||||
|
||||
// https://stackoverflow.com/a/61722734/16255372
|
||||
QTextCursor cursor = textCursor();
|
||||
QTextCharFormat format = cursor.charFormat();
|
||||
format.setForeground(QColor(0, 127, 255));
|
||||
|
||||
if (userData != nullptr && !script->expired()) {
|
||||
int id = stackTraceScriptsLastId++;
|
||||
stackTraceScripts[id] = *script;
|
||||
|
||||
format.setAnchor(true);
|
||||
format.setAnchorHref(QString::number(id));
|
||||
}
|
||||
|
||||
cursor.insertText(message.c_str(), format);
|
||||
cursor.insertText("\n", QTextCharFormat());
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/61722734/16255372
|
||||
void OutputTextView::mousePressEvent(QMouseEvent *e) {
|
||||
QString anchor = anchorAt(e->pos());
|
||||
if (anchor == "" || e->modifiers() & Qt::AltModifier) return QTextEdit::mousePressEvent(e);
|
||||
|
||||
auto script = stackTraceScripts[anchor.toInt()];
|
||||
if (script.expired()) return QTextEdit::mousePressEvent(e);
|
||||
|
||||
MainWindow* mainWnd = dynamic_cast<MainWindow*>(window());
|
||||
mainWnd->openScriptDocument(script.lock());
|
||||
}
|
||||
|
||||
void OutputTextView::mouseReleaseEvent(QMouseEvent *e) {
|
||||
return QTextEdit::mouseReleaseEvent(e);
|
||||
}
|
||||
|
||||
void OutputTextView::mouseMoveEvent(QMouseEvent *e) {
|
||||
QCursor cur = cursor();
|
||||
|
||||
QString anchor = anchorAt(e->pos());
|
||||
if (anchor == "" || e->modifiers() & Qt::AltModifier) {
|
||||
viewport()->setCursor(Qt::IBeamCursor);
|
||||
} else {
|
||||
viewport()->setCursor(Qt::PointingHandCursor);
|
||||
}
|
||||
|
||||
return QTextEdit::mouseMoveEvent(e);
|
||||
}
|
25
editor/panes/outputtextview.h
Normal file
25
editor/panes/outputtextview.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include "logger.h"
|
||||
#include <memory>
|
||||
#include <qobjectdefs.h>
|
||||
#include <qtextedit.h>
|
||||
|
||||
class Script;
|
||||
|
||||
class OutputTextView : public QTextEdit {
|
||||
Q_OBJECT
|
||||
private:
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
|
||||
void handleLog(Logger::LogLevel, std::string);
|
||||
void handleLogTrace(std::string, std::string, int, void*);
|
||||
|
||||
std::map<int, std::weak_ptr<Script>> stackTraceScripts;
|
||||
int stackTraceScriptsLastId = 0;
|
||||
public:
|
||||
OutputTextView(QWidget* parent = nullptr);
|
||||
~OutputTextView() override;
|
||||
};
|
Loading…
Add table
Reference in a new issue