Compare commits
No commits in common. "9ca0bb0cec3e2eea2b5f9d5dda055887173853db" and "cc87d08dad735a2fae22d15711b5af9d51b02c7b" have entirely different histories.
9ca0bb0cec
...
cc87d08dad
13 changed files with 41 additions and 246 deletions
|
@ -4,12 +4,10 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
static std::ofstream logStream;
|
static std::ofstream logStream;
|
||||||
static std::vector<Logger::LogListener> logListeners;
|
static std::vector<Logger::LogListener> logListeners;
|
||||||
static std::vector<Logger::TraceLogListener> traceLogListeners;
|
|
||||||
std::string Logger::currentLogDir = "NULL";
|
std::string Logger::currentLogDir = "NULL";
|
||||||
|
|
||||||
void Logger::init() {
|
void Logger::init() {
|
||||||
|
@ -31,7 +29,6 @@ void Logger::finish() {
|
||||||
void Logger::log(std::string message, Logger::LogLevel logLevel) {
|
void Logger::log(std::string message, Logger::LogLevel logLevel) {
|
||||||
std::string logLevelStr = logLevel == Logger::LogLevel::INFO ? "INFO" :
|
std::string logLevelStr = logLevel == Logger::LogLevel::INFO ? "INFO" :
|
||||||
logLevel == Logger::LogLevel::DEBUG ? "DEBUG" :
|
logLevel == Logger::LogLevel::DEBUG ? "DEBUG" :
|
||||||
logLevel == Logger::LogLevel::TRACE ? "TRACE" :
|
|
||||||
logLevel == Logger::LogLevel::WARNING ? "WARN" :
|
logLevel == Logger::LogLevel::WARNING ? "WARN" :
|
||||||
logLevel == Logger::LogLevel::ERROR ? "ERROR" :
|
logLevel == Logger::LogLevel::ERROR ? "ERROR" :
|
||||||
logLevel == Logger::LogLevel::FATAL_ERROR ? "FATAL" : "?";
|
logLevel == Logger::LogLevel::FATAL_ERROR ? "FATAL" : "?";
|
||||||
|
@ -52,20 +49,6 @@ void Logger::log(std::string message, Logger::LogLevel logLevel) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::trace(std::string source, int line, void* userData) {
|
|
||||||
std::string message = "'" + source + "' Line " + std::to_string(line);
|
|
||||||
|
|
||||||
log(message, Logger::LogLevel::TRACE);
|
|
||||||
|
|
||||||
for (Logger::TraceLogListener listener : traceLogListeners) {
|
|
||||||
listener(message, source, line, userData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::addLogListener(Logger::LogListener listener) {
|
void Logger::addLogListener(Logger::LogListener listener) {
|
||||||
logListeners.push_back(listener);
|
logListeners.push_back(listener);
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::addLogListener(Logger::TraceLogListener listener) {
|
|
||||||
traceLogListeners.push_back(listener);
|
|
||||||
}
|
}
|
|
@ -8,21 +8,18 @@ namespace Logger {
|
||||||
enum class LogLevel {
|
enum class LogLevel {
|
||||||
INFO,
|
INFO,
|
||||||
DEBUG,
|
DEBUG,
|
||||||
TRACE,
|
|
||||||
WARNING,
|
WARNING,
|
||||||
ERROR,
|
ERROR,
|
||||||
FATAL_ERROR,
|
FATAL_ERROR,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::function<void(LogLevel logLevel, std::string message)> LogListener;
|
typedef std::function<void(LogLevel logLeve, std::string message)> LogListener;
|
||||||
typedef std::function<void(std::string message, std::string source, int line, void* userData)> TraceLogListener;
|
|
||||||
|
|
||||||
extern std::string currentLogDir;
|
extern std::string currentLogDir;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void finish();
|
void finish();
|
||||||
void addLogListener(LogListener);
|
void addLogListener(LogListener);
|
||||||
void addLogListener(TraceLogListener);
|
|
||||||
|
|
||||||
void log(std::string message, LogLevel logLevel);
|
void log(std::string message, LogLevel logLevel);
|
||||||
inline void info(std::string message) { log(message, LogLevel::INFO); }
|
inline void info(std::string message) { log(message, LogLevel::INFO); }
|
||||||
|
@ -31,10 +28,6 @@ namespace Logger {
|
||||||
inline void error(std::string message) { log(message, LogLevel::ERROR); }
|
inline void error(std::string message) { log(message, LogLevel::ERROR); }
|
||||||
inline void fatalError(std::string message) { log(message, LogLevel::FATAL_ERROR); }
|
inline void fatalError(std::string message) { log(message, LogLevel::FATAL_ERROR); }
|
||||||
|
|
||||||
inline void traceStart() { log("Stack start", LogLevel::TRACE); }
|
|
||||||
inline void traceEnd() { log("Stack end", LogLevel::TRACE); }
|
|
||||||
void trace(std::string source, int line, void* userData = nullptr);
|
|
||||||
|
|
||||||
template <typename ...Args>
|
template <typename ...Args>
|
||||||
void logf(std::string format, LogLevel logLevel, Args&&... args) {
|
void logf(std::string format, LogLevel logLevel, Args&&... args) {
|
||||||
char message[200];
|
char message[200];
|
||||||
|
|
|
@ -429,17 +429,4 @@ std::vector<std::pair<std::string, std::shared_ptr<Instance>>> Instance::GetRefe
|
||||||
}
|
}
|
||||||
|
|
||||||
return referenceProperties;
|
return referenceProperties;
|
||||||
}
|
|
||||||
|
|
||||||
std::string Instance::GetFullName() {
|
|
||||||
std::string currentName = name;
|
|
||||||
std::optional<std::shared_ptr<Instance>> currentParent = GetParent();
|
|
||||||
|
|
||||||
while (currentParent.has_value() && !currentParent.value()->IsA("DataModel")) {
|
|
||||||
currentName = currentParent.value()->name + "." + currentName;
|
|
||||||
|
|
||||||
currentParent = currentParent.value()->GetParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentName;
|
|
||||||
}
|
}
|
|
@ -113,7 +113,6 @@ public:
|
||||||
// Utility functions
|
// Utility functions
|
||||||
inline void AddChild(std::shared_ptr<Instance> object) { object->SetParent(this->shared_from_this()); }
|
inline void AddChild(std::shared_ptr<Instance> object) { object->SetParent(this->shared_from_this()); }
|
||||||
std::optional<std::shared_ptr<Instance>> FindFirstChild(std::string);
|
std::optional<std::shared_ptr<Instance>> FindFirstChild(std::string);
|
||||||
std::string GetFullName();
|
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
result<Data::Variant, MemberNotFound> GetPropertyValue(std::string name);
|
result<Data::Variant, MemberNotFound> GetPropertyValue(std::string name);
|
||||||
|
|
|
@ -22,8 +22,7 @@ Script::Script(): Instance(&TYPE) {
|
||||||
"workspace.Part.TouchEnded:Connect(function(otherPart)\n"
|
"workspace.Part.TouchEnded:Connect(function(otherPart)\n"
|
||||||
" print(\"Touched ended with: \", otherPart.Name)\n"
|
" print(\"Touched ended with: \", otherPart.Name)\n"
|
||||||
"end)\n"
|
"end)\n"
|
||||||
"\n"
|
"\n";
|
||||||
"error(\"Test\")";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Script::~Script() {
|
Script::~Script() {
|
||||||
|
@ -58,39 +57,12 @@ void Script::Run() {
|
||||||
lua_pop(Lt, 1); // _G
|
lua_pop(Lt, 1); // _G
|
||||||
|
|
||||||
// Load source and push onto thread stack as function ptr
|
// Load source and push onto thread stack as function ptr
|
||||||
// luaL_loadstring(Lt, source.c_str());
|
luaL_loadstring(Lt, source.c_str());
|
||||||
luaL_loadbuffer(Lt, source.c_str(), source.size(), scriptContext->RegisterScriptSource(shared<Script>()).c_str());
|
|
||||||
|
|
||||||
int status = lua_resume(Lt, 0);
|
int status = lua_resume(Lt, 0);
|
||||||
if (status > LUA_YIELD) {
|
if (status > LUA_YIELD) {
|
||||||
lua_Debug dbg;
|
Logger::error(lua_tostring(Lt, -1));
|
||||||
lua_getstack(Lt, 1, &dbg);
|
|
||||||
lua_getinfo(Lt, "S", &dbg);
|
|
||||||
|
|
||||||
std::weak_ptr<Script> source = scriptContext->GetScriptFromSource(dbg.source);
|
|
||||||
|
|
||||||
std::string errorMessage = lua_tostring(Lt, -1);
|
|
||||||
if (!source.expired())
|
|
||||||
errorMessage = source.lock()->GetFullName() + errorMessage.substr(errorMessage.find(':'));
|
|
||||||
|
|
||||||
Logger::error(errorMessage);
|
|
||||||
lua_pop(Lt, 1); // Pop return value
|
lua_pop(Lt, 1); // Pop return value
|
||||||
|
|
||||||
Logger::traceStart();
|
|
||||||
|
|
||||||
int stack = 1;
|
|
||||||
while (lua_getstack(Lt, stack++, &dbg)) {
|
|
||||||
lua_getinfo(Lt, "nlSu", &dbg);
|
|
||||||
|
|
||||||
std::weak_ptr<Script> source = scriptContext->GetScriptFromSource(dbg.source);
|
|
||||||
if (source.expired()) {
|
|
||||||
Logger::trace(dbg.source, dbg.currentline);
|
|
||||||
} else {
|
|
||||||
Logger::trace(source.lock()->GetFullName(), dbg.currentline, &source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger::traceEnd();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_pop(L, 1); // Pop the thread
|
lua_pop(L, 1); // Pop the thread
|
||||||
|
|
|
@ -4,8 +4,9 @@
|
||||||
#include "datatypes/vector.h"
|
#include "datatypes/vector.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "timeutil.h"
|
#include "timeutil.h"
|
||||||
|
#include <cstdint>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <string>
|
#include <chrono>
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
||||||
static int g_print(lua_State*);
|
static int g_print(lua_State*);
|
||||||
|
@ -129,23 +130,6 @@ 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::weak_ptr<Script> ScriptContext::GetScriptFromSource(std::string source) {
|
|
||||||
int id = std::stoi(source.c_str() + 2);
|
|
||||||
return scriptSources[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://www.lua.org/source/5.1/lbaselib.c.html
|
// https://www.lua.org/source/5.1/lbaselib.c.html
|
||||||
static int g_print(lua_State* L) {
|
static int g_print(lua_State* L) {
|
||||||
std::string buf;
|
std::string buf;
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#include "objects/annotation.h"
|
#include "objects/annotation.h"
|
||||||
#include "objects/base/service.h"
|
#include "objects/base/service.h"
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct SleepingThread {
|
struct SleepingThread {
|
||||||
|
@ -13,14 +12,10 @@ struct SleepingThread {
|
||||||
bool active = true;
|
bool active = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Script;
|
|
||||||
|
|
||||||
class DEF_INST_SERVICE ScriptContext : public Service {
|
class DEF_INST_SERVICE ScriptContext : public Service {
|
||||||
AUTOGEN_PREAMBLE
|
AUTOGEN_PREAMBLE
|
||||||
|
|
||||||
std::vector<SleepingThread> sleepingThreads;
|
std::vector<SleepingThread> sleepingThreads;
|
||||||
std::map<int, std::weak_ptr<Script>> scriptSources;
|
|
||||||
int lastScriptSourceId = 0;
|
|
||||||
protected:
|
protected:
|
||||||
void InitService() override;
|
void InitService() override;
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
|
@ -32,8 +27,6 @@ public:
|
||||||
lua_State* state;
|
lua_State* state;
|
||||||
void PushThreadSleep(lua_State* thread, float delay);
|
void PushThreadSleep(lua_State* thread, float delay);
|
||||||
void RunSleepingThreads();
|
void RunSleepingThreads();
|
||||||
std::string RegisterScriptSource(std::shared_ptr<Script>);
|
|
||||||
std::weak_ptr<Script> GetScriptFromSource(std::string source);
|
|
||||||
|
|
||||||
static inline std::shared_ptr<Instance> Create() { return std::make_shared<ScriptContext>(); };
|
static inline std::shared_ptr<Instance> Create() { return std::make_shared<ScriptContext>(); };
|
||||||
};
|
};
|
|
@ -24,16 +24,14 @@ set(PROJECT_SOURCES
|
||||||
mainwindow.ui
|
mainwindow.ui
|
||||||
mainglwidget.h
|
mainglwidget.h
|
||||||
mainglwidget.cpp
|
mainglwidget.cpp
|
||||||
placedocument.h
|
|
||||||
placedocument.cpp
|
|
||||||
panes/explorerview.h
|
panes/explorerview.h
|
||||||
panes/explorerview.cpp
|
panes/explorerview.cpp
|
||||||
panes/explorermodel.h
|
panes/explorermodel.h
|
||||||
panes/explorermodel.cpp
|
panes/explorermodel.cpp
|
||||||
panes/propertiesview.h
|
panes/propertiesview.h
|
||||||
panes/propertiesview.cpp
|
panes/propertiesview.cpp
|
||||||
panes/outputtextview.h
|
placedocument.h
|
||||||
panes/outputtextview.cpp
|
placedocument.cpp
|
||||||
script/scriptdocument.h
|
script/scriptdocument.h
|
||||||
script/scriptdocument.cpp
|
script/scriptdocument.cpp
|
||||||
${TS_FILES}
|
${TS_FILES}
|
||||||
|
|
|
@ -5,10 +5,8 @@
|
||||||
#include "objects/datamodel.h"
|
#include "objects/datamodel.h"
|
||||||
#include "placedocument.h"
|
#include "placedocument.h"
|
||||||
#include "script/scriptdocument.h"
|
#include "script/scriptdocument.h"
|
||||||
#include <cstdio>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <qclipboard.h>
|
#include <qclipboard.h>
|
||||||
#include <qevent.h>
|
|
||||||
#include <qglobal.h>
|
#include <qglobal.h>
|
||||||
#include <qmessagebox.h>
|
#include <qmessagebox.h>
|
||||||
#include <qmimedata.h>
|
#include <qmimedata.h>
|
||||||
|
@ -17,8 +15,6 @@
|
||||||
#include <qstylehints.h>
|
#include <qstylehints.h>
|
||||||
#include <qmdisubwindow.h>
|
#include <qmdisubwindow.h>
|
||||||
#include <pugixml.hpp>
|
#include <pugixml.hpp>
|
||||||
#include <qtextcursor.h>
|
|
||||||
#include <qtextedit.h>
|
|
||||||
|
|
||||||
#ifdef _NDEBUG
|
#ifdef _NDEBUG
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
|
@ -83,6 +79,26 @@ MainWindow::MainWindow(QWidget *parent)
|
||||||
this->close();
|
this->close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Logger
|
||||||
|
|
||||||
|
Logger::addLogListener(std::bind(&MainWindow::handleLog, this, std::placeholders::_1, std::placeholders::_2));
|
||||||
|
|
||||||
|
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();
|
connectActionHandlers();
|
||||||
|
|
||||||
// Update properties
|
// Update properties
|
||||||
|
@ -140,6 +156,17 @@ void MainWindow::closeEvent(QCloseEvent* evt) {
|
||||||
#endif
|
#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::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::connectActionHandlers() {
|
void MainWindow::connectActionHandlers() {
|
||||||
// Explorer View
|
// Explorer View
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,7 @@ private:
|
||||||
|
|
||||||
void updateToolbars();
|
void updateToolbars();
|
||||||
void closeEvent(QCloseEvent* evt) override;
|
void closeEvent(QCloseEvent* evt) override;
|
||||||
|
void handleLog(Logger::LogLevel, std::string);
|
||||||
|
|
||||||
void connectActionHandlers();
|
void connectActionHandlers();
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,7 @@
|
||||||
<widget class="QWidget" name="dockWidgetContents_3">
|
<widget class="QWidget" name="dockWidgetContents_3">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
<item>
|
<item>
|
||||||
<widget class="OutputTextView" name="outputTextView">
|
<widget class="QPlainTextEdit" name="outputTextView">
|
||||||
<property name="readOnly">
|
<property name="readOnly">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
@ -780,11 +780,6 @@
|
||||||
<extends>QTreeView</extends>
|
<extends>QTreeView</extends>
|
||||||
<header>panes/propertiesview.h</header>
|
<header>panes/propertiesview.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
<customwidget>
|
|
||||||
<class>OutputTextView</class>
|
|
||||||
<extends>QTextEdit</extends>
|
|
||||||
<header>panes/outputtextview.h</header>
|
|
||||||
</customwidget>
|
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
|
|
@ -1,112 +0,0 @@
|
||||||
#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);
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
#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