feat: 一些 Bug 修复和脚本处理相关
This commit is contained in:
parent
d8069aedde
commit
c01ca038a3
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -25,43 +25,49 @@
|
||||||
|
|
||||||
AngelObjString::AngelObjString() {}
|
AngelObjString::AngelObjString() {}
|
||||||
|
|
||||||
QString AngelObjString::stringToString(void *obj, asDebugger *dbg) {
|
QString AngelObjString::stringToString(void *obj, asDebugger *dbg, asUINT tag) {
|
||||||
Q_UNUSED(dbg);
|
Q_UNUSED(dbg);
|
||||||
|
|
||||||
// We know the received object is a string
|
// We know the received object is a string
|
||||||
QString val = *reinterpret_cast<QString *>(obj);
|
QString val = *reinterpret_cast<QString *>(obj);
|
||||||
|
if (tag == 1) {
|
||||||
|
val.prepend('"').append('"');
|
||||||
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AngelObjString::arrayToString(void *obj, asDebugger *dbg) {
|
QString AngelObjString::arrayToString(void *obj, asDebugger *dbg, asUINT tag) {
|
||||||
CScriptArray *arr = reinterpret_cast<CScriptArray *>(obj);
|
CScriptArray *arr = reinterpret_cast<CScriptArray *>(obj);
|
||||||
|
|
||||||
QString str;
|
QString str;
|
||||||
QTextStream s(&str);
|
QTextStream s(&str);
|
||||||
s << tr("(len=") << arr->GetSize() << QStringLiteral(")");
|
s << QStringLiteral("{");
|
||||||
|
|
||||||
s << QStringLiteral(" [");
|
|
||||||
for (asUINT n = 0; n < arr->GetSize(); n++) {
|
for (asUINT n = 0; n < arr->GetSize(); n++) {
|
||||||
s << dbg->toString(arr->At(n), arr->GetElementTypeId(),
|
s << dbg->toString(arr->At(n), arr->GetElementTypeId(),
|
||||||
arr->GetArrayObjectType()->GetEngine());
|
arr->GetArrayObjectType()->GetEngine(), 1);
|
||||||
if (n < arr->GetSize() - 1)
|
if (n < arr->GetSize() - 1)
|
||||||
s << ", ";
|
s << ", ";
|
||||||
}
|
}
|
||||||
s << QStringLiteral("]");
|
s << QStringLiteral("}");
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AngelObjString::charToString(void *obj, asDebugger *dbg) {
|
QString AngelObjString::charToString(void *obj, asDebugger *dbg, asUINT tag) {
|
||||||
|
|
||||||
Q_UNUSED(dbg);
|
Q_UNUSED(dbg);
|
||||||
|
|
||||||
// We know the received object is a char
|
// We know the received object is a char
|
||||||
QChar *val = reinterpret_cast<QChar *>(obj);
|
QChar *val = reinterpret_cast<QChar *>(obj);
|
||||||
return QString(*val);
|
auto ret = QString(*val);
|
||||||
|
if (tag == 1) {
|
||||||
|
ret.prepend('\'').append('\'');
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AngelObjString::dictionaryToString(void *obj, asDebugger *dbg) {
|
QString AngelObjString::dictionaryToString(void *obj, asDebugger *dbg,
|
||||||
|
asUINT tag) {
|
||||||
CScriptDictionary *dic = reinterpret_cast<CScriptDictionary *>(obj);
|
CScriptDictionary *dic = reinterpret_cast<CScriptDictionary *>(obj);
|
||||||
|
|
||||||
QString str;
|
QString str;
|
||||||
|
@ -69,11 +75,11 @@ QString AngelObjString::dictionaryToString(void *obj, asDebugger *dbg) {
|
||||||
|
|
||||||
auto engine = dic->GetEngine();
|
auto engine = dic->GetEngine();
|
||||||
|
|
||||||
s << " {";
|
s << QStringLiteral("{");
|
||||||
asUINT n = 0;
|
asUINT n = 0;
|
||||||
for (CScriptDictionary::CIterator it = dic->begin(); it != dic->end();
|
for (CScriptDictionary::CIterator it = dic->begin(); it != dic->end();
|
||||||
it++, n++) {
|
it++, n++) {
|
||||||
s << "[" << it.GetKey() << "] = ";
|
s << QStringLiteral("[") << it.GetKey() << QStringLiteral("] = ");
|
||||||
|
|
||||||
// Get the type and address of the value
|
// Get the type and address of the value
|
||||||
const void *val = it.GetAddressOfValue();
|
const void *val = it.GetAddressOfValue();
|
||||||
|
@ -83,17 +89,17 @@ QString AngelObjString::dictionaryToString(void *obj, asDebugger *dbg) {
|
||||||
// active, the debugger will use the engine held inside it by
|
// active, the debugger will use the engine held inside it by
|
||||||
// default, but in an environment where there multiple engines this
|
// default, but in an environment where there multiple engines this
|
||||||
// might not be the correct instance).
|
// might not be the correct instance).
|
||||||
s << dbg->toString(const_cast<void *>(val), typeId, engine);
|
s << dbg->toString(const_cast<void *>(val), typeId, engine, 1);
|
||||||
|
|
||||||
if (n < dic->GetSize() - 1)
|
if (n < dic->GetSize() - 1)
|
||||||
s << ", ";
|
s << QStringLiteral(", ");
|
||||||
}
|
}
|
||||||
s << "}";
|
s << QStringLiteral("}");
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AngelObjString::colorToString(void *obj, asDebugger *dbg) {
|
QString AngelObjString::colorToString(void *obj, asDebugger *dbg, asUINT tag) {
|
||||||
Q_UNUSED(dbg);
|
Q_UNUSED(dbg);
|
||||||
|
|
||||||
auto color = reinterpret_cast<QColor *>(obj);
|
auto color = reinterpret_cast<QColor *>(obj);
|
||||||
|
|
|
@ -28,16 +28,15 @@ class AngelObjString : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// for debugger use
|
static QString stringToString(void *obj, asDebugger *dbg, asUINT tag);
|
||||||
static QString stringToString(void *obj, asDebugger *dbg);
|
|
||||||
|
|
||||||
static QString arrayToString(void *obj, asDebugger *dbg);
|
static QString arrayToString(void *obj, asDebugger *dbg, asUINT tag);
|
||||||
|
|
||||||
static QString charToString(void *obj, asDebugger *dbg);
|
static QString charToString(void *obj, asDebugger *dbg, asUINT tag);
|
||||||
|
|
||||||
static QString dictionaryToString(void *obj, asDebugger *dbg);
|
static QString dictionaryToString(void *obj, asDebugger *dbg, asUINT tag);
|
||||||
|
|
||||||
static QString colorToString(void *obj, asDebugger *dbg);
|
static QString colorToString(void *obj, asDebugger *dbg, asUINT tag);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// ==================================================
|
// ==================================================
|
||||||
|
|
|
@ -143,8 +143,9 @@ AppManager::AppManager(int &argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
AppManager::~AppManager() {
|
AppManager::~AppManager() {
|
||||||
InspectQtLogHelper::instance().destory();
|
|
||||||
ClangFormatManager::instance().save();
|
ClangFormatManager::instance().save();
|
||||||
|
ScriptMachine::instance().deleteLater();
|
||||||
|
InspectQtLogHelper::instance().destory();
|
||||||
CommandHistoryManager::save(QConsoleWidget::history().strings_);
|
CommandHistoryManager::save(QConsoleWidget::history().strings_);
|
||||||
|
|
||||||
delete _w;
|
delete _w;
|
||||||
|
@ -155,7 +156,7 @@ AppManager *AppManager::instance() { return _instance; }
|
||||||
|
|
||||||
MainWindow *AppManager::mainWindow() const { return _w; }
|
MainWindow *AppManager::mainWindow() const { return _w; }
|
||||||
|
|
||||||
uint AppManager::currentMSecsSinceEpoch() { return _timer.elapsed(); }
|
quint64 AppManager::currentMSecsSinceEpoch() { return _timer.elapsed(); }
|
||||||
|
|
||||||
void AppManager::openFile(const QString &file, bool autoDetect) {
|
void AppManager::openFile(const QString &file, bool autoDetect) {
|
||||||
EditorView *editor = nullptr;
|
EditorView *editor = nullptr;
|
||||||
|
|
|
@ -38,7 +38,7 @@ public:
|
||||||
QApplication::tr("WingCloudStudio");
|
QApplication::tr("WingCloudStudio");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint currentMSecsSinceEpoch();
|
quint64 currentMSecsSinceEpoch();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void openFile(const QString &file, bool autoDetect = true);
|
void openFile(const QString &file, bool autoDetect = true);
|
||||||
|
|
|
@ -414,6 +414,10 @@ QList<CodeInfoTip> AsCompletion::parseDocument() {
|
||||||
// first preprocess the code
|
// first preprocess the code
|
||||||
AsPreprocesser prepc(engine);
|
AsPreprocesser prepc(engine);
|
||||||
prepc.setIncludeCallback(&AsCompletion::includeCallBack, this);
|
prepc.setIncludeCallback(&AsCompletion::includeCallBack, this);
|
||||||
|
prepc.setPragmaCallback([](const QByteArray &, AsPreprocesser *,
|
||||||
|
const QString &,
|
||||||
|
void *) -> int { return asSUCCESS; },
|
||||||
|
nullptr);
|
||||||
|
|
||||||
auto r = prepc.loadSectionFromMemory(QStringLiteral("ASCOMPLETION"),
|
auto r = prepc.loadSectionFromMemory(QStringLiteral("ASCOMPLETION"),
|
||||||
code.toUtf8());
|
code.toUtf8());
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "asdebugger.h"
|
#include "asdebugger.h"
|
||||||
|
#include "class/appmanager.h"
|
||||||
#include "define.h"
|
#include "define.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
@ -78,6 +79,40 @@ void asDebugger::lineCallback(asIScriptContext *ctx) {
|
||||||
if (ctx == nullptr)
|
if (ctx == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// By default we ignore callbacks when the context is not active.
|
||||||
|
// An application might override this to for example disconnect the
|
||||||
|
// debugger as the execution finished.
|
||||||
|
if (ctx->GetState() != asEXECUTION_ACTIVE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto now = AppManager::instance()->currentMSecsSinceEpoch();
|
||||||
|
auto timer = reinterpret_cast<asPWORD>(
|
||||||
|
ctx->GetUserData(AsUserDataType::UserData_Timer));
|
||||||
|
auto mode = ScriptMachine::ConsoleMode(reinterpret_cast<asPWORD>(
|
||||||
|
ctx->GetUserData(AsUserDataType::UserData_ContextMode)));
|
||||||
|
|
||||||
|
bool timeOut = false;
|
||||||
|
if (timer < 0) {
|
||||||
|
timeOut = true;
|
||||||
|
} else {
|
||||||
|
if (mode == ScriptMachine::DefineEvaluator) {
|
||||||
|
timeOut = (now - timer) > 3000; // 3 s
|
||||||
|
} else {
|
||||||
|
timeOut = (now - timer) > 600000; // 10 min
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeOut) {
|
||||||
|
auto timeOut = tr("ScriptTimedOut");
|
||||||
|
ScriptMachine::MessageInfo info;
|
||||||
|
info.message = timeOut;
|
||||||
|
info.mode = mode;
|
||||||
|
info.type = ScriptMachine::MessageType::Error;
|
||||||
|
ScriptMachine::instance().outputMessage(info);
|
||||||
|
ctx->Abort();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto isDbg = reinterpret_cast<asPWORD>(
|
auto isDbg = reinterpret_cast<asPWORD>(
|
||||||
ctx->GetUserData(AsUserDataType::UserData_isDbg));
|
ctx->GetUserData(AsUserDataType::UserData_isDbg));
|
||||||
if (!isDbg) {
|
if (!isDbg) {
|
||||||
|
@ -107,12 +142,6 @@ void asDebugger::lineCallback(asIScriptContext *ctx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// By default we ignore callbacks when the context is not active.
|
|
||||||
// An application might override this to for example disconnect the
|
|
||||||
// debugger as the execution finished.
|
|
||||||
if (ctx->GetState() != asEXECUTION_ACTIVE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto dbgContext = reinterpret_cast<ContextDbgInfo *>(ctx->GetUserData());
|
auto dbgContext = reinterpret_cast<ContextDbgInfo *>(ctx->GetUserData());
|
||||||
Q_ASSERT(dbgContext);
|
Q_ASSERT(dbgContext);
|
||||||
|
|
||||||
|
@ -368,7 +397,7 @@ bool asDebugger::checkBreakPoint(asIScriptContext *ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QString asDebugger::toString(void *value, asUINT typeId,
|
QString asDebugger::toString(void *value, asUINT typeId,
|
||||||
asIScriptEngine *engine) {
|
asIScriptEngine *engine, asUINT tag) {
|
||||||
if (value == nullptr)
|
if (value == nullptr)
|
||||||
return QStringLiteral("<null>");
|
return QStringLiteral("<null>");
|
||||||
|
|
||||||
|
@ -445,7 +474,8 @@ QString asDebugger::toString(void *value, asUINT typeId,
|
||||||
s << name /*type->GetPropertyDeclaration(n)*/
|
s << name /*type->GetPropertyDeclaration(n)*/
|
||||||
<< QStringLiteral(" = ")
|
<< QStringLiteral(" = ")
|
||||||
<< toString(obj->GetAddressOfProperty(n),
|
<< toString(obj->GetAddressOfProperty(n),
|
||||||
obj->GetPropertyTypeId(n), type->GetEngine());
|
obj->GetPropertyTypeId(n), type->GetEngine(),
|
||||||
|
1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -482,7 +512,7 @@ QString asDebugger::toString(void *value, asUINT typeId,
|
||||||
|
|
||||||
// Invoke the callback to get the string representation of
|
// Invoke the callback to get the string representation of
|
||||||
// this type
|
// this type
|
||||||
s << it.value()(value, this);
|
s << it.value()(value, this, tag);
|
||||||
} else {
|
} else {
|
||||||
// Unknown type: type + address
|
// Unknown type: type + address
|
||||||
s << type->GetName() << '(' << value << ')';
|
s << type->GetName() << '(' << value << ')';
|
||||||
|
|
|
@ -84,7 +84,7 @@ public:
|
||||||
virtual ~asDebugger();
|
virtual ~asDebugger();
|
||||||
|
|
||||||
// Register callbacks to handle to-string conversions of application types
|
// Register callbacks to handle to-string conversions of application types
|
||||||
typedef QString (*ToStringCallback)(void *obj, asDebugger *dbg);
|
typedef QString (*ToStringCallback)(void *obj, asDebugger *dbg, asUINT tag);
|
||||||
|
|
||||||
void registerToStringCallback(const asITypeInfo *ti,
|
void registerToStringCallback(const asITypeInfo *ti,
|
||||||
ToStringCallback callback);
|
ToStringCallback callback);
|
||||||
|
@ -108,8 +108,9 @@ public:
|
||||||
// Line callback invoked by context
|
// Line callback invoked by context
|
||||||
void lineCallback(asIScriptContext *ctx);
|
void lineCallback(asIScriptContext *ctx);
|
||||||
|
|
||||||
|
// tag = 1 : string should be printed with quotes
|
||||||
QString toString(void *value, asUINT typeId,
|
QString toString(void *value, asUINT typeId,
|
||||||
asIScriptEngine *engine = nullptr);
|
asIScriptEngine *engine = nullptr, asUINT tag = 0);
|
||||||
|
|
||||||
GCStatistic gcStatistics();
|
GCStatistic gcStatistics();
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "aspreprocesser.h"
|
#include "aspreprocesser.h"
|
||||||
|
#include "class/scriptmachine.h"
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
#include <QStack>
|
||||||
|
|
||||||
Q_GLOBAL_STATIC_WITH_ARGS(
|
Q_GLOBAL_STATIC_WITH_ARGS(
|
||||||
QStringList, DEFAULT_MARCO,
|
QStringList, DEFAULT_MARCO,
|
||||||
|
@ -36,7 +38,9 @@ AsPreprocesser::AsPreprocesser(asIScriptEngine *engine) : engine(engine) {
|
||||||
pragmaCallback = nullptr;
|
pragmaCallback = nullptr;
|
||||||
pragmaParam = nullptr;
|
pragmaParam = nullptr;
|
||||||
|
|
||||||
definedWords = *DEFAULT_MARCO;
|
for (auto &m : *DEFAULT_MARCO) {
|
||||||
|
definedWords.insert(m, {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AsPreprocesser::~AsPreprocesser() { void ClearAll(); }
|
AsPreprocesser::~AsPreprocesser() { void ClearAll(); }
|
||||||
|
@ -85,9 +89,10 @@ void AsPreprocesser::setPragmaCallback(PRAGMACALLBACK_t callback,
|
||||||
pragmaParam = userParam;
|
pragmaParam = userParam;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsPreprocesser::defineWord(const QString &word) {
|
void AsPreprocesser::defineWord(const QString &word,
|
||||||
|
const DefineValueType &value) {
|
||||||
if (!definedWords.contains(word)) {
|
if (!definedWords.contains(word)) {
|
||||||
definedWords.append(word);
|
definedWords.insert(word, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +119,8 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
|
||||||
// shouldn't be compiled
|
// shouldn't be compiled
|
||||||
QByteArray::size_type pos = 0;
|
QByteArray::size_type pos = 0;
|
||||||
|
|
||||||
int nested = 0;
|
QStack<std::optional<bool>> m_condtionStack;
|
||||||
|
|
||||||
while (pos < modifiedScript.size()) {
|
while (pos < modifiedScript.size()) {
|
||||||
asUINT len = 0;
|
asUINT len = 0;
|
||||||
asETokenClass t = engine->ParseToken(modifiedScript.data() + pos,
|
asETokenClass t = engine->ParseToken(modifiedScript.data() + pos,
|
||||||
|
@ -128,10 +134,14 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
|
||||||
modifiedScript.size() - pos, &len);
|
modifiedScript.size() - pos, &len);
|
||||||
Q_UNUSED(t);
|
Q_UNUSED(t);
|
||||||
|
|
||||||
QByteArray token = modifiedScript.mid(pos, len);
|
QByteArray token = modifiedScript.sliced(pos, len);
|
||||||
pos += len;
|
pos += len;
|
||||||
|
|
||||||
if (token == "if") {
|
bool isIf = token == QStringLiteral("if");
|
||||||
|
bool isIfDef = token == QStringLiteral("ifdef");
|
||||||
|
bool isIfnDef = token == QStringLiteral("ifndef");
|
||||||
|
|
||||||
|
if (isIf || isIfDef || isIfnDef) {
|
||||||
t = engine->ParseToken(modifiedScript.data() + pos,
|
t = engine->ParseToken(modifiedScript.data() + pos,
|
||||||
modifiedScript.size() - pos, &len);
|
modifiedScript.size() - pos, &len);
|
||||||
if (t == asTC_WHITESPACE) {
|
if (t == asTC_WHITESPACE) {
|
||||||
|
@ -140,34 +150,87 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
|
||||||
modifiedScript.size() - pos, &len);
|
modifiedScript.size() - pos, &len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t == asTC_IDENTIFIER) {
|
if (isIfDef || isIfnDef) {
|
||||||
QByteArray word = modifiedScript.mid(pos, len);
|
if (t == asTC_IDENTIFIER) {
|
||||||
|
QByteArray word = modifiedScript.sliced(pos, len);
|
||||||
|
|
||||||
// Overwrite the #if directive with space characters to
|
// Overwrite the directive with space characters to
|
||||||
// avoid compiler error
|
// avoid compiler error
|
||||||
pos += len;
|
pos += len;
|
||||||
overwriteCode(modifiedScript, start, pos - start);
|
overwriteCode(modifiedScript, start, pos - start);
|
||||||
|
|
||||||
// Has this identifier been defined by the application or
|
// Has this identifier been defined by the application
|
||||||
// not?
|
// or not?
|
||||||
if (!definedWords.contains(word)) {
|
if ((isIfDef && !definedWords.contains(word)) ||
|
||||||
// Exclude all the code until and including the #endif
|
(isIfnDef && definedWords.contains(word))) {
|
||||||
pos = excludeCode(modifiedScript, pos);
|
// Exclude all the code until and including the
|
||||||
|
// #endif
|
||||||
|
pos = excludeCode(modifiedScript, pos);
|
||||||
|
m_condtionStack.push(false);
|
||||||
|
} else {
|
||||||
|
m_condtionStack.push(true);
|
||||||
|
}
|
||||||
|
qDebug().noquote() << modifiedScript;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// evalutate the string
|
||||||
|
auto npos = modifiedScript.indexOf('\n', pos);
|
||||||
|
auto codes = modifiedScript.sliced(pos, npos - pos);
|
||||||
|
overwriteCode(modifiedScript, start, npos - start);
|
||||||
|
|
||||||
|
auto &sm = ScriptMachine::instance();
|
||||||
|
bool ok = false;
|
||||||
|
auto ret = sm.evaluateDefine(codes, ok);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
return asERROR;
|
||||||
} else {
|
} else {
|
||||||
nested++;
|
if (ok) {
|
||||||
|
m_condtionStack.push(true);
|
||||||
|
} else {
|
||||||
|
pos = excludeCode(modifiedScript, npos);
|
||||||
|
m_condtionStack.push(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug().noquote() << modifiedScript;
|
||||||
|
}
|
||||||
|
} else if (token == "else") {
|
||||||
|
if (m_condtionStack.isEmpty()) {
|
||||||
|
// TODO
|
||||||
|
return asERROR;
|
||||||
|
} else {
|
||||||
|
overwriteCode(modifiedScript, start, pos - start);
|
||||||
|
auto opBool = m_condtionStack.top();
|
||||||
|
if (opBool) {
|
||||||
|
if (opBool.value()) {
|
||||||
|
pos = excludeCode(modifiedScript, pos);
|
||||||
|
m_condtionStack.top().reset();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// TODO
|
||||||
|
return asERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
qDebug().noquote() << modifiedScript;
|
||||||
} else if (token == "endif") {
|
} else if (token == "endif") {
|
||||||
// Only remove the #endif if there was a matching #if
|
// Only remove the #endif if there was a matching #if
|
||||||
if (nested > 0) {
|
if (m_condtionStack.isEmpty()) {
|
||||||
|
// TODO
|
||||||
|
return asERROR;
|
||||||
|
} else {
|
||||||
overwriteCode(modifiedScript, start, pos - start);
|
overwriteCode(modifiedScript, start, pos - start);
|
||||||
nested--;
|
m_condtionStack.pop();
|
||||||
}
|
}
|
||||||
|
qDebug().noquote() << modifiedScript;
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
pos += len;
|
pos += len;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qDebug().noquote() << modifiedScript;
|
||||||
|
|
||||||
// Then check for pre-processor directives
|
// Then check for pre-processor directives
|
||||||
pos = 0;
|
pos = 0;
|
||||||
while (pos >= 0 && pos < modifiedScript.size()) {
|
while (pos >= 0 && pos < modifiedScript.size()) {
|
||||||
|
@ -178,7 +241,7 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
|
||||||
pos += len;
|
pos += len;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
QString token = modifiedScript.mid(pos, len);
|
QString token = modifiedScript.sliced(pos, len);
|
||||||
|
|
||||||
// Skip possible decorators before class and interface declarations
|
// Skip possible decorators before class and interface declarations
|
||||||
if (token == "shared" || token == "abstract" || token == "mixin" ||
|
if (token == "shared" || token == "abstract" || token == "mixin" ||
|
||||||
|
@ -194,7 +257,7 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
|
||||||
t = engine->ParseToken(modifiedScript.data() + pos,
|
t = engine->ParseToken(modifiedScript.data() + pos,
|
||||||
modifiedScript.size() - pos, &len);
|
modifiedScript.size() - pos, &len);
|
||||||
if (t == asTC_IDENTIFIER) {
|
if (t == asTC_IDENTIFIER) {
|
||||||
token = modifiedScript.mid(pos, len);
|
token = modifiedScript.sliced(pos, len);
|
||||||
if (token == "include") {
|
if (token == "include") {
|
||||||
pos += len;
|
pos += len;
|
||||||
t = engine->ParseToken(modifiedScript.data() + pos,
|
t = engine->ParseToken(modifiedScript.data() + pos,
|
||||||
|
@ -211,7 +274,7 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
|
||||||
modifiedScript[pos] == '\'')) {
|
modifiedScript[pos] == '\'')) {
|
||||||
// Get the include file
|
// Get the include file
|
||||||
QString includefile =
|
QString includefile =
|
||||||
modifiedScript.mid(pos + 1, len - 2);
|
modifiedScript.sliced(pos + 1, len - 2);
|
||||||
pos += len;
|
pos += len;
|
||||||
|
|
||||||
// Make sure the includeFile doesn't contain any
|
// Make sure the includeFile doesn't contain any
|
||||||
|
@ -255,7 +318,8 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
QString includefile =
|
QString includefile =
|
||||||
modifiedScript.mid(pos, rpos - pos).trimmed();
|
modifiedScript.sliced(pos, rpos - pos)
|
||||||
|
.trimmed();
|
||||||
|
|
||||||
pos = rpos + 1;
|
pos = rpos + 1;
|
||||||
|
|
||||||
|
@ -303,7 +367,7 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
|
||||||
|
|
||||||
// Call the pragma callback
|
// Call the pragma callback
|
||||||
auto pragmaText =
|
auto pragmaText =
|
||||||
modifiedScript.mid(start + 7, pos - start - 7);
|
modifiedScript.sliced(start + 7, pos - start - 7);
|
||||||
|
|
||||||
// Overwrite the pragma directive with space characters
|
// Overwrite the pragma directive with space characters
|
||||||
// to avoid compiler error
|
// to avoid compiler error
|
||||||
|
@ -449,27 +513,32 @@ int AsPreprocesser::skipStatement(const QByteArray &modifiedScript, int pos) {
|
||||||
|
|
||||||
int AsPreprocesser::excludeCode(QByteArray &modifiedScript, int pos) {
|
int AsPreprocesser::excludeCode(QByteArray &modifiedScript, int pos) {
|
||||||
asUINT len = 0;
|
asUINT len = 0;
|
||||||
int nested = 0;
|
int nested = 1;
|
||||||
while (pos < (int)modifiedScript.size()) {
|
while (pos < (int)modifiedScript.size()) {
|
||||||
engine->ParseToken(modifiedScript.data() + pos,
|
engine->ParseToken(modifiedScript.data() + pos,
|
||||||
modifiedScript.size() - pos, &len);
|
modifiedScript.size() - pos, &len);
|
||||||
if (modifiedScript[pos] == '#') {
|
if (modifiedScript[pos] == '#') {
|
||||||
modifiedScript[pos] = ' ';
|
auto sharpPos = pos;
|
||||||
pos++;
|
pos++;
|
||||||
|
|
||||||
// Is it an #if or #endif directive?
|
// Is it an #if or #endif directive?
|
||||||
engine->ParseToken(modifiedScript.data() + pos,
|
engine->ParseToken(modifiedScript.data() + pos,
|
||||||
modifiedScript.size() - pos, &len);
|
modifiedScript.size() - pos, &len);
|
||||||
QString token = modifiedScript.mid(pos, len);
|
QString token = modifiedScript.sliced(pos, len);
|
||||||
overwriteCode(modifiedScript, pos, len);
|
|
||||||
|
|
||||||
if (token == "if") {
|
if (token == "if" || token == "ifdef" || token == "ifndef") {
|
||||||
|
modifiedScript[sharpPos] = ' ';
|
||||||
|
overwriteCode(modifiedScript, pos, len);
|
||||||
nested++;
|
nested++;
|
||||||
} else if (token == "endif") {
|
} else if (token == "endif" || token == "else") {
|
||||||
if (nested-- == 0) {
|
if (nested-- == 0) {
|
||||||
pos += len;
|
pos = sharpPos - 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
modifiedScript[sharpPos] = ' ';
|
||||||
|
overwriteCode(modifiedScript, pos, len);
|
||||||
|
} else {
|
||||||
|
modifiedScript[sharpPos] = ' ';
|
||||||
|
overwriteCode(modifiedScript, pos, len);
|
||||||
}
|
}
|
||||||
} else if (modifiedScript[pos] != '\n') {
|
} else if (modifiedScript[pos] != '\n') {
|
||||||
overwriteCode(modifiedScript, pos, len);
|
overwriteCode(modifiedScript, pos, len);
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#pragma warning(disable : 4786)
|
#pragma warning(disable : 4786)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <QEventLoop>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
@ -62,6 +63,16 @@ typedef int (*PRAGMACALLBACK_t)(const QByteArray &pragmaText,
|
||||||
// Helper class for loading and pre-processing script files to
|
// Helper class for loading and pre-processing script files to
|
||||||
// support include directives declarations
|
// support include directives declarations
|
||||||
|
|
||||||
|
/** for macros, we support:
|
||||||
|
* * #if <conditions>
|
||||||
|
* * #else
|
||||||
|
* * #endif
|
||||||
|
* * #define <word>
|
||||||
|
* * #define <word> <string|int64|double>
|
||||||
|
* * #undef <word>
|
||||||
|
* * #ifdef <word>
|
||||||
|
* * #ifundef <word>
|
||||||
|
*/
|
||||||
class AsPreprocesser {
|
class AsPreprocesser {
|
||||||
public:
|
public:
|
||||||
explicit AsPreprocesser(asIScriptEngine *engine);
|
explicit AsPreprocesser(asIScriptEngine *engine);
|
||||||
|
@ -73,6 +84,9 @@ public:
|
||||||
QByteArray script;
|
QByteArray script;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using DefineValueType =
|
||||||
|
std::variant<std::monostate, QString, qint64, double>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Load a script section from a file on disk
|
// Load a script section from a file on disk
|
||||||
// Returns 1 if the file was included
|
// Returns 1 if the file was included
|
||||||
|
@ -93,7 +107,7 @@ public:
|
||||||
void setPragmaCallback(PRAGMACALLBACK_t callback, void *userParam);
|
void setPragmaCallback(PRAGMACALLBACK_t callback, void *userParam);
|
||||||
|
|
||||||
// Add a pre-processor define for conditional compilation
|
// Add a pre-processor define for conditional compilation
|
||||||
void defineWord(const QString &word);
|
void defineWord(const QString &word, const DefineValueType &value = {});
|
||||||
|
|
||||||
// Enumerate included script sections
|
// Enumerate included script sections
|
||||||
unsigned int sectionCount() const;
|
unsigned int sectionCount() const;
|
||||||
|
@ -124,7 +138,8 @@ protected:
|
||||||
|
|
||||||
QStringList includedScripts;
|
QStringList includedScripts;
|
||||||
|
|
||||||
QStringList definedWords;
|
QEventLoop waitLoop;
|
||||||
|
QHash<QString, DefineValueType> definedWords;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ASPREPROCESSER_H
|
#endif // ASPREPROCESSER_H
|
||||||
|
|
|
@ -43,7 +43,75 @@
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QScopeGuard>
|
#include <QScopeGuard>
|
||||||
|
|
||||||
ScriptMachine::~ScriptMachine() { destoryMachine(); }
|
class StringFormatter {
|
||||||
|
public:
|
||||||
|
static QString format(const QString &input, uint indentSize = 4) {
|
||||||
|
QString output;
|
||||||
|
int level = 0;
|
||||||
|
bool inString = false;
|
||||||
|
QChar stringDelim;
|
||||||
|
bool escape = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < input.size(); ++i) {
|
||||||
|
QChar c = input[i];
|
||||||
|
|
||||||
|
if (inString) {
|
||||||
|
output += c;
|
||||||
|
if (escape) {
|
||||||
|
escape = false;
|
||||||
|
} else if (c == '\\') {
|
||||||
|
escape = true;
|
||||||
|
} else if (c == stringDelim) {
|
||||||
|
inString = false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isQuote(c)) {
|
||||||
|
inString = true;
|
||||||
|
stringDelim = c;
|
||||||
|
output += c;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (c.unicode()) {
|
||||||
|
case '{':
|
||||||
|
output += QStringLiteral("{\n");
|
||||||
|
++level;
|
||||||
|
output += QString(level * indentSize, ' ');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '}':
|
||||||
|
output += QStringLiteral("\n");
|
||||||
|
--level;
|
||||||
|
output +=
|
||||||
|
QString(level * indentSize, ' ') + QStringLiteral("}");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ',':
|
||||||
|
output +=
|
||||||
|
QStringLiteral(",\n") + QString(level * indentSize, ' ');
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (c.isSpace()) {
|
||||||
|
// collapse multiple spaces outside strings
|
||||||
|
if (!output.isEmpty() && !output.endsWith(' ')) {
|
||||||
|
output += ' ';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output += c;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool isQuote(QChar c) { return c == '"' || c == '\''; }
|
||||||
|
};
|
||||||
|
|
||||||
bool ScriptMachine::init() {
|
bool ScriptMachine::init() {
|
||||||
if (isInited()) {
|
if (isInited()) {
|
||||||
|
@ -77,6 +145,8 @@ bool ScriptMachine::configureEngine() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_engine->SetDefaultAccessMask(0x1);
|
||||||
|
|
||||||
// we need utf8, the default is what we want
|
// we need utf8, the default is what we want
|
||||||
_engine->SetEngineProperty(asEP_EXPAND_DEF_ARRAY_TO_TMPL, true);
|
_engine->SetEngineProperty(asEP_EXPAND_DEF_ARRAY_TO_TMPL, true);
|
||||||
_engine->SetEngineProperty(asEP_DISALLOW_EMPTY_LIST_ELEMENTS, true);
|
_engine->SetEngineProperty(asEP_DISALLOW_EMPTY_LIST_ELEMENTS, true);
|
||||||
|
@ -155,6 +225,22 @@ bool ScriptMachine::configureEngine() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r = _engine->RegisterGlobalFunction("string stringify(? &in obj)",
|
||||||
|
asMETHOD(ScriptMachine, stringify),
|
||||||
|
asCALL_THISCALL_ASGLOBAL, this);
|
||||||
|
Q_ASSERT(r >= 0);
|
||||||
|
if (r < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = _engine->RegisterGlobalFunction(
|
||||||
|
"string beautify(const string &in str, uint indent = 4)",
|
||||||
|
asFUNCTION(beautify), asCALL_CDECL);
|
||||||
|
Q_ASSERT(r >= 0);
|
||||||
|
if (r < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
r = _engine->RegisterGlobalFunction(
|
r = _engine->RegisterGlobalFunction(
|
||||||
"int exec(string &out output, const string &in exe, "
|
"int exec(string &out output, const string &in exe, "
|
||||||
"const string &in params = \"\", int timeout = 3000)",
|
"const string &in params = \"\", int timeout = 3000)",
|
||||||
|
@ -198,7 +284,8 @@ bool ScriptMachine::configureEngine() {
|
||||||
PluginSystem::instance().angelApi()->installAPI(this);
|
PluginSystem::instance().angelApi()->installAPI(this);
|
||||||
|
|
||||||
// create module for Console
|
// create module for Console
|
||||||
_engine->GetModule("WINGCONSOLE", asGM_ALWAYS_CREATE);
|
auto mod = _engine->GetModule("WINGCONSOLE", asGM_ALWAYS_CREATE);
|
||||||
|
mod->SetAccessMask(0x1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -317,8 +404,21 @@ int ScriptMachine::execSystemCmd(QString &out, const QString &exe,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ScriptMachine::beautify(const QString &str, uint indent) {
|
||||||
|
return StringFormatter::format(str, indent);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ScriptMachine::stringify(void *ref, int typeId) {
|
||||||
|
return _debugger->toString(ref, typeId, _engine);
|
||||||
|
}
|
||||||
|
|
||||||
bool ScriptMachine::executeScript(ConsoleMode mode, const QString &script,
|
bool ScriptMachine::executeScript(ConsoleMode mode, const QString &script,
|
||||||
bool isInDebug) {
|
bool isInDebug, int *retCode) {
|
||||||
|
Q_ASSERT(mode != Interactive && mode != DefineEvaluator);
|
||||||
|
if (script.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Compile the script
|
// Compile the script
|
||||||
auto mod = createModule(mode);
|
auto mod = createModule(mode);
|
||||||
// script-running is not allowed in interactive mode
|
// script-running is not allowed in interactive mode
|
||||||
|
@ -326,13 +426,11 @@ bool ScriptMachine::executeScript(ConsoleMode mode, const QString &script,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QScopeGuard guard([mod, mode]() {
|
QScopeGuard guard([mod]() {
|
||||||
if (mode != ConsoleMode::Interactive) {
|
// Before leaving, allow the engine to clean up remaining objects by
|
||||||
// Before leaving, allow the engine to clean up remaining objects by
|
// discarding the module and doing a full garbage collection so that
|
||||||
// discarding the module and doing a full garbage collection so that
|
// this can also be debugged if desired
|
||||||
// this can also be debugged if desired
|
mod->Discard();
|
||||||
mod->Discard();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
asPWORD isDbg = 0;
|
asPWORD isDbg = 0;
|
||||||
|
@ -353,12 +451,13 @@ bool ScriptMachine::executeScript(ConsoleMode mode, const QString &script,
|
||||||
builder.setPragmaCallback(&ScriptMachine::pragmaCallback, this);
|
builder.setPragmaCallback(&ScriptMachine::pragmaCallback, this);
|
||||||
builder.setIncludeCallback(&ScriptMachine::includeCallback, this);
|
builder.setIncludeCallback(&ScriptMachine::includeCallback, this);
|
||||||
|
|
||||||
|
_curMode = mode;
|
||||||
auto r = builder.loadSectionFromFile(script.toUtf8());
|
auto r = builder.loadSectionFromFile(script.toUtf8());
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
|
// TODO
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_curMode = mode;
|
|
||||||
r = builder.build(mod);
|
r = builder.build(mod);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
MessageInfo info;
|
MessageInfo info;
|
||||||
|
@ -414,6 +513,9 @@ bool ScriptMachine::executeScript(ConsoleMode mode, const QString &script,
|
||||||
asIScriptContext *ctx = _ctxMgr->AddContext(_engine, func, true);
|
asIScriptContext *ctx = _ctxMgr->AddContext(_engine, func, true);
|
||||||
_ctx[mode] = ctx;
|
_ctx[mode] = ctx;
|
||||||
|
|
||||||
|
ctx->SetUserData(reinterpret_cast<void *>(
|
||||||
|
AppManager::instance()->currentMSecsSinceEpoch()),
|
||||||
|
AsUserDataType::UserData_Timer);
|
||||||
ctx->SetUserData(reinterpret_cast<void *>(isDbg),
|
ctx->SetUserData(reinterpret_cast<void *>(isDbg),
|
||||||
AsUserDataType::UserData_isDbg);
|
AsUserDataType::UserData_isDbg);
|
||||||
|
|
||||||
|
@ -492,9 +594,79 @@ bool ScriptMachine::executeScript(ConsoleMode mode, const QString &script,
|
||||||
_debugger->clearBreakPoint();
|
_debugger->clearBreakPoint();
|
||||||
emit onDebugFinished();
|
emit onDebugFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (retCode) {
|
||||||
|
*retCode = r;
|
||||||
|
}
|
||||||
|
|
||||||
return r >= 0;
|
return r >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ScriptMachine::evaluateDefine(const QString &code, bool &result) {
|
||||||
|
auto mod = createModuleIfNotExist(DefineEvaluator);
|
||||||
|
if (mod) {
|
||||||
|
asIScriptFunction *func = nullptr;
|
||||||
|
|
||||||
|
auto ccode = code;
|
||||||
|
ccode.prepend("bool f(){ return (").append(");}");
|
||||||
|
// start to compile
|
||||||
|
_curMode = DefineEvaluator;
|
||||||
|
auto cr = mod->CompileFunction(nullptr, ccode.toUtf8(), 0, 0, &func);
|
||||||
|
if (cr < 0) {
|
||||||
|
return cr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up a context to execute the script
|
||||||
|
// The context manager will request the context from the
|
||||||
|
// pool, which will automatically attach the debugger
|
||||||
|
asIScriptContext *ctx = _ctxMgr->AddContext(_engine, func, true);
|
||||||
|
_ctx[DefineEvaluator] = ctx;
|
||||||
|
|
||||||
|
ctx->SetUserData(reinterpret_cast<void *>(asPWORD(
|
||||||
|
AppManager::instance()->currentMSecsSinceEpoch())),
|
||||||
|
AsUserDataType::UserData_Timer);
|
||||||
|
|
||||||
|
asPWORD isDbg = 0;
|
||||||
|
ctx->SetUserData(reinterpret_cast<void *>(isDbg),
|
||||||
|
AsUserDataType::UserData_isDbg);
|
||||||
|
mod->SetUserData(reinterpret_cast<void *>(isDbg),
|
||||||
|
AsUserDataType::UserData_isDbg);
|
||||||
|
|
||||||
|
asPWORD umode = asPWORD(DefineEvaluator);
|
||||||
|
ctx->SetUserData(reinterpret_cast<void *>(umode),
|
||||||
|
AsUserDataType::UserData_ContextMode);
|
||||||
|
|
||||||
|
ctx->SetExceptionCallback(asMETHOD(ScriptMachine, exceptionCallback),
|
||||||
|
this, asCALL_THISCALL);
|
||||||
|
|
||||||
|
// Execute the script until completion
|
||||||
|
// The script may create co-routines. These will automatically
|
||||||
|
// be managed by the context manager
|
||||||
|
while (_ctxMgr->ExecuteScripts()) {
|
||||||
|
qApp->processEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
_ctx[DefineEvaluator] = nullptr;
|
||||||
|
|
||||||
|
// Check if the main script finished normally
|
||||||
|
int r = ctx->GetState();
|
||||||
|
if (r != asEXECUTION_FINISHED) {
|
||||||
|
r = -1;
|
||||||
|
} else {
|
||||||
|
result = bool(ctx->GetReturnByte());
|
||||||
|
r = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
func->Release();
|
||||||
|
|
||||||
|
// Return the context after retrieving the return value
|
||||||
|
_ctxMgr->DoneWithContext(ctx);
|
||||||
|
_engine->GarbageCollect();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
return asERROR;
|
||||||
|
}
|
||||||
|
|
||||||
void ScriptMachine::abortDbgScript() {
|
void ScriptMachine::abortDbgScript() {
|
||||||
if (_debugger->getEngine()) {
|
if (_debugger->getEngine()) {
|
||||||
_debugger->runDebugAction(asDebugger::ABORT);
|
_debugger->runDebugAction(asDebugger::ABORT);
|
||||||
|
@ -573,29 +745,51 @@ asIScriptModule *ScriptMachine::createModule(ConsoleMode mode) {
|
||||||
if (isModuleExists(mode)) {
|
if (isModuleExists(mode)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asIScriptModule *mod = nullptr;
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case Interactive:
|
case Interactive:
|
||||||
return nullptr;
|
mod = nullptr;
|
||||||
case Scripting:
|
case Scripting:
|
||||||
return _engine->GetModule("WINGSCRIPT", asGM_ALWAYS_CREATE);
|
mod = _engine->GetModule("WINGSCRIPT", asGM_ALWAYS_CREATE);
|
||||||
|
mod->SetAccessMask(0x1);
|
||||||
|
break;
|
||||||
case Background:
|
case Background:
|
||||||
return _engine->GetModule("WINGSRV", asGM_ALWAYS_CREATE);
|
mod = _engine->GetModule("WINGSRV", asGM_ALWAYS_CREATE);
|
||||||
|
mod->SetAccessMask(0x1);
|
||||||
|
break;
|
||||||
|
case DefineEvaluator:
|
||||||
|
mod = _engine->GetModule("WINGDEF", asGM_ALWAYS_CREATE);
|
||||||
|
mod->SetAccessMask(0x2);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// should not go there
|
|
||||||
return nullptr;
|
return mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
asIScriptModule *ScriptMachine::createModuleIfNotExist(ConsoleMode mode) {
|
asIScriptModule *ScriptMachine::createModuleIfNotExist(ConsoleMode mode) {
|
||||||
|
asIScriptModule *mod = nullptr;
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case Interactive:
|
case Interactive:
|
||||||
return _engine->GetModule("WINGCONSOLE", asGM_ONLY_IF_EXISTS);
|
mod = _engine->GetModule("WINGCONSOLE", asGM_ONLY_IF_EXISTS);
|
||||||
|
mod->SetAccessMask(0x1);
|
||||||
|
break;
|
||||||
case Scripting:
|
case Scripting:
|
||||||
return _engine->GetModule("WINGSCRIPT", asGM_CREATE_IF_NOT_EXISTS);
|
mod = _engine->GetModule("WINGSCRIPT", asGM_CREATE_IF_NOT_EXISTS);
|
||||||
|
mod->SetAccessMask(0x1);
|
||||||
|
break;
|
||||||
case Background:
|
case Background:
|
||||||
return _engine->GetModule("WINGSRV", asGM_CREATE_IF_NOT_EXISTS);
|
mod = _engine->GetModule("WINGSRV", asGM_CREATE_IF_NOT_EXISTS);
|
||||||
|
mod->SetAccessMask(0x1);
|
||||||
|
break;
|
||||||
|
case DefineEvaluator:
|
||||||
|
mod = _engine->GetModule("WINGDEF", asGM_ALWAYS_CREATE);
|
||||||
|
mod->SetAccessMask(0x2);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// should not go there
|
|
||||||
return nullptr;
|
return mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
asIScriptModule *ScriptMachine::module(ConsoleMode mode) {
|
asIScriptModule *ScriptMachine::module(ConsoleMode mode) {
|
||||||
|
@ -606,6 +800,8 @@ asIScriptModule *ScriptMachine::module(ConsoleMode mode) {
|
||||||
return _engine->GetModule("WINGSCRIPT", asGM_ONLY_IF_EXISTS);
|
return _engine->GetModule("WINGSCRIPT", asGM_ONLY_IF_EXISTS);
|
||||||
case Background:
|
case Background:
|
||||||
return _engine->GetModule("WINGSRV", asGM_ONLY_IF_EXISTS);
|
return _engine->GetModule("WINGSRV", asGM_ONLY_IF_EXISTS);
|
||||||
|
case DefineEvaluator:
|
||||||
|
return _engine->GetModule("WINGDEF", asGM_ONLY_IF_EXISTS);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -1832,6 +2028,10 @@ asIScriptEngine *ScriptMachine::engine() const { return _engine; }
|
||||||
asDebugger *ScriptMachine::debugger() const { return _debugger; }
|
asDebugger *ScriptMachine::debugger() const { return _debugger; }
|
||||||
|
|
||||||
bool ScriptMachine::executeCode(ConsoleMode mode, const QString &code) {
|
bool ScriptMachine::executeCode(ConsoleMode mode, const QString &code) {
|
||||||
|
if (code.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
asIScriptModule *mod = createModuleIfNotExist(mode);
|
asIScriptModule *mod = createModuleIfNotExist(mode);
|
||||||
_engine->SetEngineProperty(asEP_BUILD_WITHOUT_LINE_CUES, false);
|
_engine->SetEngineProperty(asEP_BUILD_WITHOUT_LINE_CUES, false);
|
||||||
|
|
||||||
|
@ -1841,26 +2041,30 @@ bool ScriptMachine::executeCode(ConsoleMode mode, const QString &code) {
|
||||||
|
|
||||||
asIScriptFunction *func = nullptr;
|
asIScriptFunction *func = nullptr;
|
||||||
|
|
||||||
auto ret = parser.parse(ccode);
|
QList<QAsCodeParser::CodeSegment> ret;
|
||||||
|
if (mode != DefineEvaluator) {
|
||||||
|
ret = parser.parse(ccode);
|
||||||
|
}
|
||||||
|
|
||||||
// check whether there is any enum/class
|
// check whether there is any enum/class
|
||||||
if (std::find_if(ret.begin(), ret.end(),
|
if (ret.isEmpty() ||
|
||||||
[](const QAsCodeParser::CodeSegment &seg) {
|
std::any_of(ret.begin(), ret.end(),
|
||||||
switch (seg.type) {
|
[](const QAsCodeParser::CodeSegment &seg) {
|
||||||
case QAsCodeParser::SymbolType::Enum:
|
switch (seg.type) {
|
||||||
case QAsCodeParser::SymbolType::Class:
|
case QAsCodeParser::SymbolType::Enum:
|
||||||
case QAsCodeParser::SymbolType::Function:
|
case QAsCodeParser::SymbolType::Class:
|
||||||
case QAsCodeParser::SymbolType::Interface:
|
case QAsCodeParser::SymbolType::Function:
|
||||||
case QAsCodeParser::SymbolType::Import:
|
case QAsCodeParser::SymbolType::Interface:
|
||||||
case QAsCodeParser::SymbolType::Variable:
|
case QAsCodeParser::SymbolType::Import:
|
||||||
return false;
|
case QAsCodeParser::SymbolType::Variable:
|
||||||
case QAsCodeParser::SymbolType::Invalid:
|
return false;
|
||||||
case QAsCodeParser::SymbolType::TypeDef:
|
case QAsCodeParser::SymbolType::Invalid:
|
||||||
case QAsCodeParser::SymbolType::FnDef:
|
case QAsCodeParser::SymbolType::TypeDef:
|
||||||
return true;
|
case QAsCodeParser::SymbolType::FnDef:
|
||||||
}
|
return true;
|
||||||
return true;
|
}
|
||||||
}) != ret.end()) {
|
return true;
|
||||||
|
})) {
|
||||||
// ok, wrap the codes
|
// ok, wrap the codes
|
||||||
ccode.prepend("void f(){").append("}");
|
ccode.prepend("void f(){").append("}");
|
||||||
// start to compile
|
// start to compile
|
||||||
|
@ -1881,6 +2085,10 @@ bool ScriptMachine::executeCode(ConsoleMode mode, const QString &code) {
|
||||||
asIScriptContext *ctx = _ctxMgr->AddContext(_engine, func, true);
|
asIScriptContext *ctx = _ctxMgr->AddContext(_engine, func, true);
|
||||||
_ctx[mode] = ctx;
|
_ctx[mode] = ctx;
|
||||||
|
|
||||||
|
ctx->SetUserData(reinterpret_cast<void *>(asPWORD(
|
||||||
|
AppManager::instance()->currentMSecsSinceEpoch())),
|
||||||
|
AsUserDataType::UserData_Timer);
|
||||||
|
|
||||||
asPWORD isDbg = 0;
|
asPWORD isDbg = 0;
|
||||||
ctx->SetUserData(reinterpret_cast<void *>(isDbg),
|
ctx->SetUserData(reinterpret_cast<void *>(isDbg),
|
||||||
AsUserDataType::UserData_isDbg);
|
AsUserDataType::UserData_isDbg);
|
||||||
|
|
|
@ -36,9 +36,10 @@ private:
|
||||||
public:
|
public:
|
||||||
// we have three console modes
|
// we have three console modes
|
||||||
enum ConsoleMode {
|
enum ConsoleMode {
|
||||||
Interactive, // in a shell
|
Interactive, // in a shell
|
||||||
Scripting, // in scripting dialog
|
Scripting, // in scripting dialog
|
||||||
Background // run codes from other way
|
Background, // run codes from other way
|
||||||
|
DefineEvaluator // define result calculator
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -108,8 +109,7 @@ public:
|
||||||
asIScriptModule *module(ConsoleMode mode);
|
asIScriptModule *module(ConsoleMode mode);
|
||||||
|
|
||||||
static ScriptMachine &instance();
|
static ScriptMachine &instance();
|
||||||
|
void destoryMachine();
|
||||||
virtual ~ScriptMachine();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool init();
|
bool init();
|
||||||
|
@ -126,6 +126,8 @@ public:
|
||||||
|
|
||||||
asIScriptEngine *engine() const;
|
asIScriptEngine *engine() const;
|
||||||
|
|
||||||
|
void outputMessage(const MessageInfo &info);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void scriptAssert(bool b);
|
static void scriptAssert(bool b);
|
||||||
static void scriptAssert_X(bool b, const QString &msg);
|
static void scriptAssert_X(bool b, const QString &msg);
|
||||||
|
@ -144,7 +146,9 @@ public slots:
|
||||||
bool executeCode(ConsoleMode mode, const QString &code);
|
bool executeCode(ConsoleMode mode, const QString &code);
|
||||||
// only scripting mode can be debugged
|
// only scripting mode can be debugged
|
||||||
bool executeScript(ConsoleMode mode, const QString &script,
|
bool executeScript(ConsoleMode mode, const QString &script,
|
||||||
bool isInDebug = false);
|
bool isInDebug = false, int *retCode = nullptr);
|
||||||
|
|
||||||
|
int evaluateDefine(const QString &code, bool &result);
|
||||||
|
|
||||||
void abortDbgScript();
|
void abortDbgScript();
|
||||||
void abortScript(ConsoleMode mode);
|
void abortScript(ConsoleMode mode);
|
||||||
|
@ -155,19 +159,19 @@ protected:
|
||||||
|
|
||||||
QString getCallStack(asIScriptContext *context);
|
QString getCallStack(asIScriptContext *context);
|
||||||
|
|
||||||
void destoryMachine();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void print(void *ref, int typeId);
|
void print(void *ref, int typeId);
|
||||||
QString getInput();
|
QString getInput();
|
||||||
|
|
||||||
void outputMessage(const MessageInfo &info);
|
|
||||||
|
|
||||||
bool isType(asITypeInfo *tinfo, RegisteredType type);
|
bool isType(asITypeInfo *tinfo, RegisteredType type);
|
||||||
|
|
||||||
static int execSystemCmd(QString &out, const QString &exe,
|
static int execSystemCmd(QString &out, const QString &exe,
|
||||||
const QString ¶ms, int timeout);
|
const QString ¶ms, int timeout);
|
||||||
|
|
||||||
|
static QString beautify(const QString &str, uint indent);
|
||||||
|
|
||||||
|
QString stringify(void *ref, int typeId);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void messageCallback(const asSMessageInfo *msg, void *param);
|
static void messageCallback(const asSMessageInfo *msg, void *param);
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ void GotoWidget::handleLineChanged() {
|
||||||
ui->lineEdit->setStyleSheet(QString());
|
ui->lineEdit->setStyleSheet(QString());
|
||||||
emit jumpToLine(p, isline);
|
emit jumpToLine(p, isline);
|
||||||
} else {
|
} else {
|
||||||
ui->lineEdit->setStyleSheet(QStringLiteral("color: red;"));
|
ui->lineEdit->setStyleSheet(QStringLiteral("QLineEdit{color: red}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -439,6 +439,12 @@ void ScriptingConsole::paste() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ScriptingConsole::isTerminal() const { return _isTerminal; }
|
||||||
|
|
||||||
|
void ScriptingConsole::setIsTerminal(bool newIsTerminal) {
|
||||||
|
_isTerminal = newIsTerminal;
|
||||||
|
}
|
||||||
|
|
||||||
QString ScriptingConsole::currentCodes() const {
|
QString ScriptingConsole::currentCodes() const {
|
||||||
QTextCursor textCursor = this->textCursor();
|
QTextCursor textCursor = this->textCursor();
|
||||||
textCursor.setPosition(inpos_, QTextCursor::KeepAnchor);
|
textCursor.setPosition(inpos_, QTextCursor::KeepAnchor);
|
||||||
|
@ -457,15 +463,18 @@ void ScriptingConsole::contextMenuEvent(QContextMenuEvent *event) {
|
||||||
menu.addAction(QIcon(QStringLiteral(":/qeditor/paste.png")), tr("Paste"),
|
menu.addAction(QIcon(QStringLiteral(":/qeditor/paste.png")), tr("Paste"),
|
||||||
QKeySequence(QKeySequence::Paste), this,
|
QKeySequence(QKeySequence::Paste), this,
|
||||||
&ScriptingConsole::paste);
|
&ScriptingConsole::paste);
|
||||||
menu.addAction(ICONRES(QStringLiteral("del")), tr("Clear"),
|
|
||||||
QKeySequence(Qt::ControlModifier | Qt::Key_L), this,
|
if (_isTerminal) {
|
||||||
&ScriptingConsole::clearConsole);
|
menu.addAction(ICONRES(QStringLiteral("del")), tr("Clear"),
|
||||||
menu.addSeparator();
|
QKeySequence(Qt::ControlModifier | Qt::Key_L), this,
|
||||||
menu.addAction(ICONRES(QStringLiteral("dbgstop")), tr("AbortScript"),
|
&ScriptingConsole::clearConsole);
|
||||||
QKeySequence(Qt::ControlModifier | Qt::Key_Q), []() {
|
menu.addSeparator();
|
||||||
ScriptMachine::instance().abortScript(
|
menu.addAction(ICONRES(QStringLiteral("dbgstop")), tr("AbortScript"),
|
||||||
ScriptMachine::Background);
|
QKeySequence(Qt::ControlModifier | Qt::Key_Q), []() {
|
||||||
});
|
ScriptMachine::instance().abortScript(
|
||||||
|
ScriptMachine::Background);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
menu.exec(event->globalPos());
|
menu.exec(event->globalPos());
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,10 @@ signals:
|
||||||
public:
|
public:
|
||||||
QString getInput();
|
QString getInput();
|
||||||
|
|
||||||
|
bool isTerminal() const;
|
||||||
|
|
||||||
|
void setIsTerminal(bool newIsTerminal);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
|
@ -71,6 +75,7 @@ protected slots:
|
||||||
private:
|
private:
|
||||||
QString _codes;
|
QString _codes;
|
||||||
|
|
||||||
|
bool _isTerminal = true;
|
||||||
bool _isWaitingRead = false;
|
bool _isWaitingRead = false;
|
||||||
std::function<QString(void)> _getInputFn;
|
std::function<QString(void)> _getInputFn;
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,18 +19,47 @@ ScriptingConsoleBase::ScriptingConsoleBase(QWidget *parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptingConsoleBase::stdOut(const QString &str) {
|
void ScriptingConsoleBase::stdOut(const QString &str) {
|
||||||
writeStdOut(str);
|
auto lines = str.split('\n');
|
||||||
dontHighlightLastLine(true);
|
if (lines.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
writeStdOut(lines.takeFirst());
|
||||||
|
dontHighlightLastLine(false);
|
||||||
|
for (auto &l : lines) {
|
||||||
|
newLine();
|
||||||
|
writeStdOut(l);
|
||||||
|
dontHighlightLastLine(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptingConsoleBase::stdErr(const QString &str) {
|
void ScriptingConsoleBase::stdErr(const QString &str) {
|
||||||
writeStdErr(str);
|
auto lines = str.split('\n');
|
||||||
|
if (lines.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeStdErr(lines.takeFirst());
|
||||||
dontHighlightLastLine(false);
|
dontHighlightLastLine(false);
|
||||||
|
for (auto &l : lines) {
|
||||||
|
newLine();
|
||||||
|
writeStdErr(l);
|
||||||
|
dontHighlightLastLine(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptingConsoleBase::stdWarn(const QString &str) {
|
void ScriptingConsoleBase::stdWarn(const QString &str) {
|
||||||
write(str, _warnCharFmt);
|
auto lines = str.split('\n');
|
||||||
|
if (lines.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
write(lines.takeFirst(), _warnCharFmt);
|
||||||
dontHighlightLastLine(false);
|
dontHighlightLastLine(false);
|
||||||
|
for (auto &l : lines) {
|
||||||
|
newLine();
|
||||||
|
write(l, _warnCharFmt);
|
||||||
|
dontHighlightLastLine(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptingConsoleBase::newLine() { _s << Qt::endl; }
|
void ScriptingConsoleBase::newLine() { _s << Qt::endl; }
|
||||||
|
|
|
@ -16,6 +16,8 @@ enum AsUserDataType {
|
||||||
UserData_PluginFn,
|
UserData_PluginFn,
|
||||||
UserData_isDbg,
|
UserData_isDbg,
|
||||||
UserData_ContextMode,
|
UserData_ContextMode,
|
||||||
|
UserData_Timer,
|
||||||
|
UserData_TimeOut
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -607,6 +607,22 @@ ads::CDockAreaWidget *MainWindow::buildUpLogDock(ads::CDockManager *dock,
|
||||||
m_logbrowser->setOpenExternalLinks(true);
|
m_logbrowser->setOpenExternalLinks(true);
|
||||||
m_logbrowser->setUndoRedoEnabled(false);
|
m_logbrowser->setUndoRedoEnabled(false);
|
||||||
|
|
||||||
|
m_logbrowser->addAction(newAction(
|
||||||
|
ICONRES("copy"), tr("Copy"), [=]() { m_logbrowser->copy(); },
|
||||||
|
QKeySequence::Copy));
|
||||||
|
|
||||||
|
auto a = new QAction(this);
|
||||||
|
a->setSeparator(true);
|
||||||
|
m_logbrowser->addAction(a);
|
||||||
|
|
||||||
|
m_logbrowser->addAction(newAction(ICONRES(QStringLiteral("log")),
|
||||||
|
tr("ExportLog"),
|
||||||
|
&MainWindow::on_exportlog));
|
||||||
|
m_logbrowser->addAction(newAction(ICONRES(QStringLiteral("clearhis")),
|
||||||
|
tr("ClearLog"), &MainWindow::on_clslog));
|
||||||
|
|
||||||
|
m_logbrowser->setContextMenuPolicy(Qt::ActionsContextMenu);
|
||||||
|
|
||||||
auto dw =
|
auto dw =
|
||||||
buildDockWidget(dock, QStringLiteral("Log"), tr("Log"), m_logbrowser);
|
buildDockWidget(dock, QStringLiteral("Log"), tr("Log"), m_logbrowser);
|
||||||
return dock->addDockWidget(area, dw, areaw);
|
return dock->addDockWidget(area, dw, areaw);
|
||||||
|
@ -803,9 +819,7 @@ MainWindow::buildUpHashResultDock(ads::CDockManager *dock,
|
||||||
m_hashtable->setContextMenuPolicy(
|
m_hashtable->setContextMenuPolicy(
|
||||||
Qt::ContextMenuPolicy::ActionsContextMenu);
|
Qt::ContextMenuPolicy::ActionsContextMenu);
|
||||||
|
|
||||||
auto a = new QAction(m_hashtable);
|
auto a = newAction(ICONRES(QStringLiteral("copy")), tr("Copy"), [=] {
|
||||||
a->setText(tr("Copy"));
|
|
||||||
connect(a, &QAction::triggered, this, [=] {
|
|
||||||
auto r = m_hashtable->currentIndex();
|
auto r = m_hashtable->currentIndex();
|
||||||
qApp->clipboard()->setText(
|
qApp->clipboard()->setText(
|
||||||
_hashModel->checkSumData(QCryptographicHash::Algorithm(r.row())));
|
_hashModel->checkSumData(QCryptographicHash::Algorithm(r.row())));
|
||||||
|
@ -813,6 +827,9 @@ MainWindow::buildUpHashResultDock(ads::CDockManager *dock,
|
||||||
tr("CopyToClipBoard"));
|
tr("CopyToClipBoard"));
|
||||||
});
|
});
|
||||||
m_hashtable->addAction(a);
|
m_hashtable->addAction(a);
|
||||||
|
a = newAction(QStringLiteral("del"), tr("Clear"),
|
||||||
|
[=]() { _hashModel->clearData(); });
|
||||||
|
m_hashtable->addAction(a);
|
||||||
connect(m_hashtable->selectionModel(),
|
connect(m_hashtable->selectionModel(),
|
||||||
&QItemSelectionModel::currentRowChanged, a,
|
&QItemSelectionModel::currentRowChanged, a,
|
||||||
[=](const QModelIndex ¤t, const QModelIndex &) {
|
[=](const QModelIndex ¤t, const QModelIndex &) {
|
||||||
|
|
|
@ -360,7 +360,7 @@ private:
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
inline QAction *newAction(const QString &title, Func &&slot,
|
inline QAction *newAction(const QString &title, Func &&slot,
|
||||||
const QKeySequence &shortcut = QKeySequence()) {
|
const QKeySequence &shortcut = QKeySequence()) {
|
||||||
auto a = new QAction;
|
auto a = new QAction(this);
|
||||||
a->setText(title);
|
a->setText(title);
|
||||||
a->setShortcutVisibleInContextMenu(true);
|
a->setShortcutVisibleInContextMenu(true);
|
||||||
a->setShortcut(shortcut);
|
a->setShortcut(shortcut);
|
||||||
|
|
|
@ -583,6 +583,7 @@ ScriptingDialog::buildUpOutputShowDock(ads::CDockManager *dock,
|
||||||
ads::CDockAreaWidget *areaw) {
|
ads::CDockAreaWidget *areaw) {
|
||||||
m_consoleout = new ScriptingConsole(this);
|
m_consoleout = new ScriptingConsole(this);
|
||||||
m_consoleout->setMode(ScriptingConsole::Output);
|
m_consoleout->setMode(ScriptingConsole::Output);
|
||||||
|
m_consoleout->setIsTerminal(false);
|
||||||
auto dw = buildDockWidget(dock, QStringLiteral("ConsoleOutput"),
|
auto dw = buildDockWidget(dock, QStringLiteral("ConsoleOutput"),
|
||||||
tr("ConsoleOutput"), m_consoleout);
|
tr("ConsoleOutput"), m_consoleout);
|
||||||
return dock->addDockWidget(area, dw, areaw);
|
return dock->addDockWidget(area, dw, areaw);
|
||||||
|
|
|
@ -170,7 +170,7 @@ private:
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
inline QAction *newAction(const QString &title, Func &&slot,
|
inline QAction *newAction(const QString &title, Func &&slot,
|
||||||
const QKeySequence &shortcut = QKeySequence()) {
|
const QKeySequence &shortcut = QKeySequence()) {
|
||||||
auto a = new QAction;
|
auto a = new QAction(this);
|
||||||
a->setText(title);
|
a->setText(title);
|
||||||
a->setShortcutVisibleInContextMenu(true);
|
a->setShortcutVisibleInContextMenu(true);
|
||||||
a->setShortcut(shortcut);
|
a->setShortcut(shortcut);
|
||||||
|
|
Loading…
Reference in New Issue