feat: 更好的代码填充;自动重载文件相关;
This commit is contained in:
parent
f59755e3f0
commit
2ee3051a7d
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -69,7 +69,7 @@ QString AngelObjString::dictionaryToString(void *obj, asDebugger *dbg) {
|
|||
|
||||
auto engine = dic->GetEngine();
|
||||
|
||||
s << " [";
|
||||
s << " {";
|
||||
asUINT n = 0;
|
||||
for (CScriptDictionary::CIterator it = dic->begin(); it != dic->end();
|
||||
it++, n++) {
|
||||
|
@ -88,7 +88,7 @@ QString AngelObjString::dictionaryToString(void *obj, asDebugger *dbg) {
|
|||
if (n < dic->GetSize() - 1)
|
||||
s << ", ";
|
||||
}
|
||||
s << "]";
|
||||
s << "}";
|
||||
|
||||
return str;
|
||||
}
|
||||
|
|
|
@ -154,11 +154,6 @@ bool AsCompletion::processTrigger(const QString &trigger,
|
|||
auto code = content.toUtf8();
|
||||
|
||||
QList<CodeInfoTip> nodes;
|
||||
QList<CodeInfoTip> docNodes;
|
||||
|
||||
if (m_parseDocument) {
|
||||
docNodes = parseDocument();
|
||||
}
|
||||
|
||||
if (!trigger.isEmpty() && trigger != *DOT_TRIGGER) {
|
||||
clearFunctionTip();
|
||||
|
@ -226,24 +221,35 @@ bool AsCompletion::processTrigger(const QString &trigger,
|
|||
return false;
|
||||
}
|
||||
|
||||
QString prefix;
|
||||
auto etoken = tokens.back();
|
||||
// it can not be any trigger, so take the last as prefix
|
||||
QString prefix = etoken.content;
|
||||
if (etoken.type == asTC_VALUE || etoken.type == asTC_COMMENT ||
|
||||
etoken.type == asTC_UNKNOWN) {
|
||||
popup()->hide();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (trigger.isEmpty() && popup()->isVisible()) {
|
||||
setCompletionPrefix(prefix);
|
||||
return true;
|
||||
}
|
||||
|
||||
QList<CodeInfoTip> docNodes;
|
||||
if (m_parseDocument) {
|
||||
docNodes = parseDocument();
|
||||
}
|
||||
|
||||
// if trigger is empty, it's making editing
|
||||
if (trigger.isEmpty()) {
|
||||
// it can not be any trigger, so take the last as prefix
|
||||
prefix = etoken.content;
|
||||
tokens.removeLast();
|
||||
if (tokens.isEmpty()) {
|
||||
applyEmptyNsNode(nodes, docNodes);
|
||||
} else {
|
||||
etoken = tokens.back(); // checking later
|
||||
}
|
||||
} else {
|
||||
prefix.clear();
|
||||
}
|
||||
|
||||
if (nodes.isEmpty()) {
|
||||
|
@ -266,8 +272,52 @@ bool AsCompletion::processTrigger(const QString &trigger,
|
|||
}
|
||||
|
||||
if (trigger == *DOT_TRIGGER) {
|
||||
// member guessing ?
|
||||
applyClassNodes(nodes);
|
||||
// member type guessing ? basic match is enough. (>n<)
|
||||
auto isBasicType = [](const QString &type) {
|
||||
static QStringList basicType{
|
||||
"int", "int8", "int16", "int32", "int64",
|
||||
"uint", "uint8", "uint16", "uint32", "uint64",
|
||||
"float", "double", "byte"};
|
||||
|
||||
return basicType.contains(type);
|
||||
};
|
||||
|
||||
auto clsNodes = parser.headerNodes();
|
||||
|
||||
// filter the type we can use to auto-complete in docNodes
|
||||
for (auto &item : docNodes) {
|
||||
if (item.type == CodeInfoTip::Type::Class) {
|
||||
auto name = item.nameSpace;
|
||||
if (name.isEmpty()) {
|
||||
name = item.name;
|
||||
}
|
||||
clsNodes.insert(name, item.children);
|
||||
}
|
||||
// a typedef can only be used to define an alias
|
||||
// for primitive types, so NO NEED for auto-completing
|
||||
}
|
||||
|
||||
tokens.removeLast();
|
||||
auto ns = getNamespace(tokens);
|
||||
for (auto &item : docNodes) {
|
||||
if (etoken.content == item.name && ns == item.nameSpace) {
|
||||
auto retType = item.addinfo.value(CodeInfoTip::RetType);
|
||||
|
||||
// auto type inference is not supported.
|
||||
// PRs will be welcomed !!!
|
||||
if (isBasicType(retType)) {
|
||||
popup()->hide();
|
||||
return false;
|
||||
}
|
||||
|
||||
nodes.append(clsNodes.value(retType));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (nodes.isEmpty()) {
|
||||
applyClassNodes(nodes);
|
||||
}
|
||||
} else if (etoken.content.length() >= triggerAmount()) {
|
||||
// completion for a.b.c or a::b.c or a::b::c.d or ::a::b.c
|
||||
if (trigger == *DBL_COLON_TRIGGER) {
|
||||
|
@ -368,6 +418,7 @@ QList<CodeInfoTip> AsCompletion::parseDocument() {
|
|||
va.dontAddGlobal = true;
|
||||
va.name = var.name;
|
||||
va.nameSpace = QString::fromUtf8(var.scope.join("::"));
|
||||
va.addinfo.insert(CodeInfoTip::RetType, var.type);
|
||||
va.type = CodeInfoTip::Type::Variable;
|
||||
ret.append(va);
|
||||
}
|
||||
|
@ -389,17 +440,47 @@ QList<CodeInfoTip> AsCompletion::parseDocument() {
|
|||
}
|
||||
break;
|
||||
case QAsCodeParser::SymbolType::TypeDef:
|
||||
tip.type = CodeInfoTip::Type::KeyWord;
|
||||
tip.type = CodeInfoTip::Type::TypeDef;
|
||||
break;
|
||||
case QAsCodeParser::SymbolType::Variable:
|
||||
tip.addinfo.insert(CodeInfoTip::RetType, sym.type);
|
||||
tip.type = CodeInfoTip::Type::Variable;
|
||||
break;
|
||||
case QAsCodeParser::SymbolType::Class:
|
||||
case QAsCodeParser::SymbolType::Interface:
|
||||
tip.type = CodeInfoTip::Type::Class;
|
||||
for (auto &mem : sym.children) {
|
||||
// TODO
|
||||
if (mem.vis != QAsCodeParser::Visiblity::Public) {
|
||||
continue;
|
||||
}
|
||||
CodeInfoTip ctip;
|
||||
ctip.name = mem.name;
|
||||
ctip.nameSpace = QString::fromUtf8(mem.scope.join("::"));
|
||||
if (mem.symtype == QAsCodeParser::SymbolType::Function) {
|
||||
ctip.type = CodeInfoTip::Type::Function;
|
||||
ctip.addinfo.insert(CodeInfoTip::RetType,
|
||||
QString::fromUtf8(mem.type));
|
||||
ctip.addinfo.insert(
|
||||
CodeInfoTip::Args,
|
||||
QString::fromUtf8(mem.additonalInfo));
|
||||
for (auto &var : mem.children) {
|
||||
CodeInfoTip va;
|
||||
va.dontAddGlobal = true;
|
||||
va.name = var.name;
|
||||
va.nameSpace =
|
||||
QString::fromUtf8(var.scope.join("::"));
|
||||
va.addinfo.insert(CodeInfoTip::RetType, var.type);
|
||||
va.type = CodeInfoTip::Type::Variable;
|
||||
tip.children.append(va);
|
||||
}
|
||||
tip.children.append(ctip);
|
||||
} else if (mem.symtype ==
|
||||
QAsCodeParser::SymbolType::Variable) {
|
||||
ctip.addinfo.insert(CodeInfoTip::RetType, mem.type);
|
||||
ctip.type = CodeInfoTip::Type::Variable;
|
||||
tip.children.append(ctip);
|
||||
}
|
||||
}
|
||||
tip.type = CodeInfoTip::Type::Class;
|
||||
break;
|
||||
case QAsCodeParser::SymbolType::Invalid:
|
||||
case QAsCodeParser::SymbolType::Import:
|
||||
|
|
|
@ -36,6 +36,7 @@ QIcon CodeInfoTip::getDisplayIcon(Type type, CodeInfoVisibility vis) {
|
|||
case Type::Group:
|
||||
return icon(ICON_NAMESPACE);
|
||||
case Type::Class:
|
||||
case Type::TypeDef:
|
||||
return icon(ICON_CLASS);
|
||||
case Type::ClsFunction:
|
||||
case Type::Function:
|
||||
|
|
|
@ -36,6 +36,7 @@ public:
|
|||
Variable,
|
||||
Property = Variable,
|
||||
Enumerater,
|
||||
TypeDef
|
||||
};
|
||||
|
||||
enum CacheIndex {
|
||||
|
|
|
@ -151,6 +151,9 @@ void CTypeParser::initialize() {
|
|||
ADD_TYPE(longlong, QMetaType::LongLong);
|
||||
ADD_TYPE_U(ulonglong, QMetaType::ULongLong);
|
||||
|
||||
using uint = unsigned int;
|
||||
ADD_TYPE_U(uint, QMetaType::UInt);
|
||||
|
||||
using BOOL = bool;
|
||||
using BYTE = byte;
|
||||
using WORD = uint16;
|
||||
|
@ -242,6 +245,8 @@ void CTypeParser::initialize() {
|
|||
|
||||
#undef ADD_TYPE
|
||||
#undef ADD_TYPE_S
|
||||
|
||||
base_types_ = type_maps_.keys();
|
||||
}
|
||||
|
||||
void CTypeParser::setIncludePaths(const QStringList &paths) {
|
||||
|
@ -627,7 +632,7 @@ TokenTypes CTypeParser::getTokenType(const QString &token) const {
|
|||
return keywords_.value(token);
|
||||
} else if (qualifiers_.contains(token)) {
|
||||
return kQualifier;
|
||||
} else if (type_maps_.contains(token)) {
|
||||
} else if (base_types_.contains(token)) {
|
||||
return kBasicDataType;
|
||||
} else if (struct_defs_.contains(token)) {
|
||||
return kStructName;
|
||||
|
|
|
@ -211,6 +211,9 @@ private:
|
|||
/// @note All enum types have fixed size, so they're not stored
|
||||
QHash<QString, QPair<QMetaType::Type, qsizetype>> type_maps_;
|
||||
|
||||
/// basic types
|
||||
QStringList base_types_;
|
||||
|
||||
/// unsigned types
|
||||
QStringList unsigned_types_;
|
||||
|
||||
|
|
|
@ -119,12 +119,26 @@ QAsCodeParser::parseIntell(qsizetype offset,
|
|||
continue;
|
||||
}
|
||||
break;
|
||||
case SymbolType::Class:
|
||||
sym.children = parseClassContent(offset, sym.scope, seg.codes);
|
||||
break;
|
||||
case SymbolType::Interface:
|
||||
sym.children = parseInterfaceContent(offset, sym.scope, seg.codes);
|
||||
break;
|
||||
case SymbolType::Class: {
|
||||
auto syms =
|
||||
parseClassContent(offset - seg.offset, sym.scope, seg.codes);
|
||||
// TODO: PRS, 'cause i have no need to code-complete a class
|
||||
sym.inherit = syms.first;
|
||||
sym.children = syms.second;
|
||||
if (offset > seg.offset && offset < seg.end()) {
|
||||
ret.append(syms.second);
|
||||
}
|
||||
} break;
|
||||
case SymbolType::Interface: {
|
||||
auto syms = parseInterfaceContent(offset - seg.offset, sym.scope,
|
||||
seg.codes);
|
||||
// TODO: PRS, 'cause i have no need to code-complete an interface
|
||||
sym.inherit = syms.first;
|
||||
sym.children = syms.second;
|
||||
if (offset > seg.offset && offset < seg.end()) {
|
||||
ret.append(syms.second);
|
||||
}
|
||||
} break;
|
||||
case SymbolType::Invalid:
|
||||
case SymbolType::Import:
|
||||
continue;
|
||||
|
@ -510,7 +524,8 @@ QAsCodeParser::parseStatementBlock(const QByteArrayList &ns,
|
|||
QList<QAsCodeParser::Symbol> ret;
|
||||
for (auto &symlist : syms) {
|
||||
for (auto &sym : symlist) {
|
||||
if (sym.symtype == SymbolType::Variable) {
|
||||
if (sym.symtype == SymbolType::Variable &&
|
||||
!sym.type.isEmpty()) {
|
||||
auto var = sym.name;
|
||||
auto n = std::find_if(
|
||||
ret.begin(), ret.end(),
|
||||
|
@ -940,13 +955,14 @@ QAsCodeParser::CodeSegment QAsCodeParser::parseFuncDef() {
|
|||
auto begin = t1.pos;
|
||||
skipCodeBlock();
|
||||
getToken(&t1);
|
||||
rewindTo(&t1);
|
||||
auto end = t1.pos;
|
||||
|
||||
// seg.name is empty
|
||||
seg.scope = currentNs;
|
||||
seg.offset = begin;
|
||||
seg.type = SymbolType::FnDef;
|
||||
seg.codes = _code.sliced(begin, end - begin + 1);
|
||||
seg.codes = _code.sliced(begin, end - begin);
|
||||
return seg;
|
||||
}
|
||||
|
||||
|
@ -1027,6 +1043,7 @@ void QAsCodeParser::superficiallyParseVarInit() {
|
|||
} while (indentParan || indentBrace ||
|
||||
(t.type != ttListSeparator && t.type != ttEndStatement &&
|
||||
t.type != ttEndStatementBlock));
|
||||
rewindTo(&t);
|
||||
} else if (t.type == ttOpenParenthesis) {
|
||||
sToken start = t;
|
||||
|
||||
|
@ -1308,6 +1325,7 @@ QAsCodeParser::CodeSegment QAsCodeParser::parseTypedef() {
|
|||
auto begin = token.pos;
|
||||
skipCodeBlock();
|
||||
getToken(&token);
|
||||
rewindTo(&token);
|
||||
auto end = token.pos;
|
||||
|
||||
// seg.name is empty
|
||||
|
@ -1423,22 +1441,27 @@ QAsCodeParser::parseGlobalVarDecls(const QByteArrayList &ns,
|
|||
return parseDeclaration(ns, false, true);
|
||||
}
|
||||
|
||||
QAsCodeParser::CodeSegment QAsCodeParser::parseFunctionMethod() {
|
||||
QAsCodeParser::CodeSegment QAsCodeParser::parseFunctionMethod(Visiblity &vis) {
|
||||
CodeSegment seg;
|
||||
|
||||
sToken t1;
|
||||
getToken(&t1);
|
||||
|
||||
vis = Visiblity::Public;
|
||||
|
||||
// A class method can start with 'private' or 'protected'
|
||||
if (t1.type == ttPrivate) {
|
||||
rewindTo(&t1);
|
||||
parseToken(ttPrivate);
|
||||
getToken(&t1);
|
||||
vis = Visiblity::Private;
|
||||
} else if (t1.type == ttProtected) {
|
||||
rewindTo(&t1);
|
||||
parseToken(ttProtected);
|
||||
getToken(&t1);
|
||||
vis = Visiblity::Protected;
|
||||
}
|
||||
|
||||
if (_isSyntaxError)
|
||||
return seg;
|
||||
|
||||
|
@ -1530,12 +1553,13 @@ QAsCodeParser::parseFuncDefContent(const QByteArrayList &ns,
|
|||
return parseFuncDefContent(ns);
|
||||
}
|
||||
|
||||
QList<QAsCodeParser::Symbol>
|
||||
QPair<QByteArrayList, QList<QAsCodeParser::Symbol>>
|
||||
QAsCodeParser::parseClassContent(qsizetype offset, const QByteArrayList &ns,
|
||||
const QByteArray &code) {
|
||||
reset();
|
||||
_code = code;
|
||||
|
||||
QByteArrayList inhertSyms;
|
||||
QList<Symbol> syms;
|
||||
|
||||
sToken t;
|
||||
|
@ -1544,32 +1568,30 @@ QAsCodeParser::parseClassContent(qsizetype offset, const QByteArrayList &ns,
|
|||
// Optional list of interfaces that are being implemented and classes that
|
||||
// are being inherited
|
||||
if (t.type == ttColon) {
|
||||
Symbol inhertSym;
|
||||
QByteArray inhertSym;
|
||||
|
||||
// assuming it as an interface
|
||||
inhertSym.symtype = SymbolType::Interface;
|
||||
|
||||
Symbol isym;
|
||||
isym.scope = parseOptionalScope();
|
||||
isym.name = getSymbolString(parseIdentifier());
|
||||
isym.symtype = SymbolType::Class; // assuming it as a class
|
||||
|
||||
inhertSym.children.append(isym);
|
||||
|
||||
inhertSym = parseOptionalScope().join("::");
|
||||
if (!inhertSym.isEmpty()) {
|
||||
inhertSym += "::";
|
||||
}
|
||||
inhertSym += getSymbolString(parseIdentifier());
|
||||
inhertSyms.append(inhertSym);
|
||||
getToken(&t);
|
||||
while (t.type == ttListSeparator) {
|
||||
isym.scope = parseOptionalScope();
|
||||
isym.name = getSymbolString(parseIdentifier());
|
||||
inhertSym.children.append(isym);
|
||||
inhertSym = parseOptionalScope().join("::");
|
||||
if (!inhertSym.isEmpty()) {
|
||||
inhertSym += "::";
|
||||
}
|
||||
inhertSym += getSymbolString(parseIdentifier());
|
||||
inhertSyms.append(inhertSym);
|
||||
getToken(&t);
|
||||
}
|
||||
|
||||
syms.append(inhertSym);
|
||||
}
|
||||
|
||||
if (t.type != ttStartStatementBlock) {
|
||||
rewindErrorTo(&t);
|
||||
return syms;
|
||||
return {inhertSyms, syms};
|
||||
}
|
||||
|
||||
// Parse properties
|
||||
|
@ -1581,11 +1603,11 @@ QAsCodeParser::parseClassContent(qsizetype offset, const QByteArrayList &ns,
|
|||
auto fndef = parseFuncDefContent(ns);
|
||||
syms.append(fndef);
|
||||
} else if (isFuncDecl(true)) {
|
||||
auto fn = parseFunctionMethod();
|
||||
Symbol sym;
|
||||
auto fn = parseFunctionMethod(sym.vis);
|
||||
|
||||
// add function symbols
|
||||
Symbol sym;
|
||||
sym.symtype = fn.type;
|
||||
sym.symtype = SymbolType::Function;
|
||||
sym.scope = fn.scope;
|
||||
sym.offset = fn.offset;
|
||||
sym.name = fn.name;
|
||||
|
@ -1595,7 +1617,8 @@ QAsCodeParser::parseClassContent(qsizetype offset, const QByteArrayList &ns,
|
|||
|
||||
// deep parsing
|
||||
if (offset >= fn.offset && offset < fn.end()) {
|
||||
auto ss = parseStatementBlock(fn.scope, fn.codes, offset);
|
||||
auto ss =
|
||||
parseStatementBlock(fn.scope, fn.codes, offset - fn.offset);
|
||||
syms.append(ss);
|
||||
}
|
||||
} else if (isVirtualPropertyDecl()) {
|
||||
|
@ -1609,11 +1632,11 @@ QAsCodeParser::parseClassContent(qsizetype offset, const QByteArrayList &ns,
|
|||
getToken(&t);
|
||||
else {
|
||||
rewindErrorTo(&t);
|
||||
return syms;
|
||||
return {inhertSyms, syms};
|
||||
}
|
||||
|
||||
if (_isSyntaxError)
|
||||
return syms;
|
||||
return {inhertSyms, syms};
|
||||
|
||||
getToken(&t);
|
||||
rewindTo(&t);
|
||||
|
@ -1622,15 +1645,16 @@ QAsCodeParser::parseClassContent(qsizetype offset, const QByteArrayList &ns,
|
|||
getToken(&t);
|
||||
if (t.type != ttEndStatementBlock) {
|
||||
rewindErrorTo(&t);
|
||||
return syms;
|
||||
return {inhertSyms, syms};
|
||||
}
|
||||
|
||||
return syms;
|
||||
return {inhertSyms, syms};
|
||||
}
|
||||
|
||||
QList<QAsCodeParser::Symbol>
|
||||
QPair<QByteArrayList, QList<QAsCodeParser::Symbol>>
|
||||
QAsCodeParser::parseInterfaceContent(qsizetype offset, const QByteArrayList &ns,
|
||||
const QByteArray &code) {
|
||||
QByteArrayList inhertSyms;
|
||||
QList<Symbol> syms;
|
||||
|
||||
sToken t;
|
||||
|
@ -1638,12 +1662,22 @@ QAsCodeParser::parseInterfaceContent(qsizetype offset, const QByteArrayList &ns,
|
|||
getToken(&t);
|
||||
// Can optionally have a list of interfaces that are inherited
|
||||
if (t.type == ttColon) {
|
||||
parseOptionalScope();
|
||||
parseIdentifier();
|
||||
QByteArray inhertSym;
|
||||
|
||||
inhertSym = parseOptionalScope().join("::");
|
||||
if (!inhertSym.isEmpty()) {
|
||||
inhertSym += "::";
|
||||
}
|
||||
inhertSym += getSymbolString(parseIdentifier());
|
||||
inhertSyms.append(inhertSym);
|
||||
getToken(&t);
|
||||
while (t.type == ttListSeparator) {
|
||||
parseOptionalScope();
|
||||
parseIdentifier();
|
||||
inhertSym = parseOptionalScope().join("::");
|
||||
if (!inhertSym.isEmpty()) {
|
||||
inhertSym += "::";
|
||||
}
|
||||
inhertSym += getSymbolString(parseIdentifier());
|
||||
inhertSyms.append(inhertSym);
|
||||
getToken(&t);
|
||||
}
|
||||
}
|
||||
|
@ -1670,7 +1704,7 @@ QAsCodeParser::parseInterfaceContent(qsizetype offset, const QByteArrayList &ns,
|
|||
}
|
||||
|
||||
if (_isSyntaxError)
|
||||
return syms;
|
||||
return {inhertSyms, syms};
|
||||
|
||||
getToken(&t);
|
||||
rewindTo(&t);
|
||||
|
@ -1679,10 +1713,10 @@ QAsCodeParser::parseInterfaceContent(qsizetype offset, const QByteArrayList &ns,
|
|||
getToken(&t);
|
||||
if (t.type != ttEndStatementBlock) {
|
||||
rewindErrorTo(&t);
|
||||
return syms;
|
||||
return {inhertSyms, syms};
|
||||
}
|
||||
|
||||
return syms;
|
||||
return {inhertSyms, syms};
|
||||
}
|
||||
|
||||
QAsCodeParser::Symbol QAsCodeParser::parseInterfaceMethod() {
|
||||
|
|
|
@ -90,6 +90,7 @@ public:
|
|||
Visiblity vis = QAsCodeParser::Visiblity::Public;
|
||||
QByteArray additonalInfo; // for other additonal info
|
||||
|
||||
QByteArrayList inherit;
|
||||
QList<Symbol> children;
|
||||
};
|
||||
|
||||
|
@ -134,7 +135,7 @@ private:
|
|||
CodeSegment parseInterface();
|
||||
CodeSegment parseFuncDef();
|
||||
CodeSegment parseFunction();
|
||||
CodeSegment parseFunctionMethod();
|
||||
CodeSegment parseFunctionMethod(Visiblity &vis);
|
||||
|
||||
private:
|
||||
// parse tokens
|
||||
|
@ -172,12 +173,13 @@ private:
|
|||
|
||||
Symbol parseFuncDefContent(const QByteArrayList &ns);
|
||||
|
||||
QList<Symbol> parseClassContent(qsizetype offset, const QByteArrayList &ns,
|
||||
const QByteArray &code);
|
||||
QPair<QByteArrayList, QList<Symbol>>
|
||||
parseClassContent(qsizetype offset, const QByteArrayList &ns,
|
||||
const QByteArray &code);
|
||||
|
||||
QList<Symbol> parseInterfaceContent(qsizetype offset,
|
||||
const QByteArrayList &ns,
|
||||
const QByteArray &code);
|
||||
QPair<QByteArrayList, QList<Symbol>>
|
||||
parseInterfaceContent(qsizetype offset, const QByteArrayList &ns,
|
||||
const QByteArray &code);
|
||||
|
||||
QList<Symbol> parseStatementBlock(const QByteArrayList &ns,
|
||||
const QByteArray &code, qsizetype end);
|
||||
|
|
|
@ -121,6 +121,9 @@ EditorView::EditorView(QWidget *parent)
|
|||
m_metadata->setDocument(doc);
|
||||
});
|
||||
|
||||
connect(&_watcher, &QFileSystemWatcher::fileChanged, this,
|
||||
&EditorView::need2Reload);
|
||||
|
||||
applySettings();
|
||||
|
||||
// build up call tables
|
||||
|
@ -284,6 +287,9 @@ ErrFile EditorView::newFile(size_t index) {
|
|||
if (isCloneFile()) {
|
||||
return ErrFile::ClonedFile;
|
||||
}
|
||||
if (!m_fileName.isEmpty()) {
|
||||
_watcher.removePath(m_fileName);
|
||||
}
|
||||
auto istr = QString::number(index);
|
||||
m_fileName = tr("Untitled") + istr;
|
||||
this->setWindowTitle(m_fileName);
|
||||
|
@ -320,6 +326,10 @@ ErrFile EditorView::openFile(const QString &filename) {
|
|||
return ErrFile::Permission;
|
||||
}
|
||||
|
||||
if (!m_fileName.isEmpty()) {
|
||||
_watcher.removePath(m_fileName);
|
||||
}
|
||||
|
||||
m_hex->setDocument(QSharedPointer<QHexDocument>(p));
|
||||
m_hex->setLockedFile(readonly);
|
||||
m_hex->setKeepSize(true);
|
||||
|
@ -335,6 +345,8 @@ ErrFile EditorView::openFile(const QString &filename) {
|
|||
auto tab = this->tabWidget();
|
||||
tab->setIcon(Utilities::getIconFromFile(style(), m_fileName));
|
||||
tab->setToolTip(m_fileName);
|
||||
|
||||
_watcher.addPath(m_fileName);
|
||||
}
|
||||
|
||||
return ErrFile::Success;
|
||||
|
@ -372,6 +384,10 @@ ErrFile EditorView::openExtFile(const QString &ext, const QString &file) {
|
|||
return ErrFile::Error;
|
||||
}
|
||||
|
||||
if (!m_fileName.isEmpty()) {
|
||||
_watcher.removePath(m_fileName);
|
||||
}
|
||||
|
||||
m_hex->setDocument(QSharedPointer<QHexDocument>(p));
|
||||
m_hex->setLockedFile(readonly);
|
||||
m_hex->setKeepSize(true);
|
||||
|
@ -562,10 +578,14 @@ ErrFile EditorView::save(const QString &workSpaceName, const QString &path,
|
|||
file.close();
|
||||
|
||||
if (!isExport) {
|
||||
if (!m_fileName.isEmpty()) {
|
||||
_watcher.removePath(m_fileName);
|
||||
}
|
||||
m_fileName = QFileInfo(fileName).absoluteFilePath();
|
||||
m_isNewFile = false;
|
||||
m_docType = DocumentType::File;
|
||||
doc->setDocSaved();
|
||||
_watcher.addPath(m_fileName);
|
||||
}
|
||||
#ifdef Q_OS_LINUX
|
||||
adjustPermission();
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#ifndef EDITORVIEW_H
|
||||
#define EDITORVIEW_H
|
||||
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QReadWriteLock>
|
||||
#include <QStackedWidget>
|
||||
|
||||
|
@ -553,6 +554,8 @@ signals:
|
|||
void sigOnMetadata();
|
||||
void sigOnBookMark();
|
||||
|
||||
void need2Reload();
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
|
||||
|
@ -589,6 +592,7 @@ private:
|
|||
|
||||
QReadWriteLock _rwlock;
|
||||
CallTable _viewFns;
|
||||
QFileSystemWatcher _watcher;
|
||||
};
|
||||
|
||||
#endif // EDITORVIEW_H
|
||||
|
|
|
@ -245,7 +245,8 @@ MainWindow::MainWindow(SplashDialog *splash) : FramelessMainWindow() {
|
|||
sm.registerCallBack(ScriptMachine::Interactive, callbacks);
|
||||
|
||||
callbacks.getInputFn = [this]() -> QString {
|
||||
return WingInputDialog::getText(this, tr(""), tr(""));
|
||||
return WingInputDialog::getText(this, tr("InputRequest"),
|
||||
tr("PleaseInput"));
|
||||
};
|
||||
callbacks.clearFn = [this]() { m_bgScriptOutput->clear(); };
|
||||
callbacks.printMsgFn =
|
||||
|
@ -3162,6 +3163,22 @@ void MainWindow::connectEditorView(EditorView *editor) {
|
|||
connect(editor, &EditorView::sigOnPasteHex, this, &MainWindow::on_pastehex);
|
||||
connect(editor, &EditorView::sigOnPasteFile, this,
|
||||
&MainWindow::on_pastefile);
|
||||
|
||||
editor->setProperty("__RELOAD__", false);
|
||||
connect(editor, &EditorView::need2Reload, this, [editor, this]() {
|
||||
if (editor->isBigFile()) {
|
||||
editor->reload();
|
||||
}
|
||||
if (currentEditor() == editor) {
|
||||
auto ret = WingMessageBox::question(this, tr("Reload"),
|
||||
tr("ReloadNeededYesOrNo"));
|
||||
if (ret == QMessageBox::Yes) {
|
||||
editor->reload();
|
||||
}
|
||||
} else {
|
||||
editor->setProperty("__RELOAD__", true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void MainWindow::swapEditor(EditorView *old, EditorView *cur) {
|
||||
|
@ -3188,6 +3205,15 @@ void MainWindow::swapEditor(EditorView *old, EditorView *cur) {
|
|||
|
||||
Q_ASSERT(cur);
|
||||
auto hexeditor = cur->hexEditor();
|
||||
auto needReload = cur->property("__RELOAD__").toBool();
|
||||
if (needReload) {
|
||||
auto ret = WingMessageBox::question(this, tr("Reload"),
|
||||
tr("ReloadNeededYesOrNo"));
|
||||
if (ret == QMessageBox::Yes) {
|
||||
cur->reload();
|
||||
}
|
||||
cur->setProperty("__RELOAD__", false);
|
||||
}
|
||||
connect(hexeditor, &QHexView::cursorLocationChanged, this,
|
||||
&MainWindow::on_locChanged);
|
||||
connect(hexeditor, &QHexView::cursorSelectionChanged, this,
|
||||
|
|
Loading…
Reference in New Issue