From 77e2a32940475893a70ecae49192ba0a40faa2a1 Mon Sep 17 00:00:00 2001 From: "royqh1979@gmail.com" Date: Wed, 10 Nov 2021 12:29:02 +0800 Subject: [PATCH 01/32] work save --- RedPandaIDE/debugger.cpp | 56 ++++++++++++++++++++++++++++-------- RedPandaIDE/debugger.h | 3 ++ RedPandaIDE/mainwindow.cpp | 58 +++++++++++++++++++------------------- 3 files changed, 77 insertions(+), 40 deletions(-) diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index 0fca8bd3..4cd44a40 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -224,10 +224,10 @@ void Debugger::setBreakPointCondition(int index, const QString &condition) { PBreakpoint breakpoint=mBreakpointModel->setBreakPointCondition(index,condition); if (condition.isEmpty()) { - sendCommand("cond", + sendCommand("-break-condition", QString("%1").arg(breakpoint->line)); } else { - sendCommand("cond", + sendCommand("-break-condition", QString("%1 %2").arg(breakpoint->line).arg(condition)); } } @@ -362,9 +362,8 @@ void Debugger::notifyAfterProcessWatchVar() void Debugger::updateDebugInfo() { - sendCommand("backtrace", ""); - sendCommand("info locals", ""); - sendCommand("info args", ""); + sendCommand("-stack-list-frames", ""); + sendCommand("-stack-list-variables", "--skip-unavailable --allvalues"); } bool Debugger::useUTF8() const @@ -403,13 +402,14 @@ void Debugger::sendBreakpointCommand(PBreakpoint breakpoint) // break "filename":linenum QString condition; if (!breakpoint->condition.isEmpty()) { - condition = " if " + breakpoint->condition; + condition = " -c " + breakpoint->condition; } QString filename = breakpoint->filename; filename.replace('\\','/'); - sendCommand("break", - QString("\"%1\":%2").arg(filename) - .arg(breakpoint->line)+condition); + sendCommand("-break-insert", + QString("%1 --source \"%2\" --line %3") + .arg(condition,filename) + .arg(breakpoint->line)); } } @@ -772,6 +772,16 @@ AnnotationType DebugReader::getNextAnnotation() return getAnnotation(getNextWord()); } +bool DebugReader::outputTerminated(QByteArray &text) +{ + QStringList lines = TextToLines(QString::fromUtf8(text)); + foreach (const QString& line,lines) { + if (line == "(gdb)") + return true; + } + return false; +} + QString DebugReader::getNextFilledLine() { // Walk up to an enter sequence @@ -1176,6 +1186,29 @@ void DebugReader::processDebugOutput() doupdatecpuwindow = false; doreceivedsfwarning = false; + QStringList lines = TextToLines(mOutput); + + mOutputLine = 0; + while (mOutputLine= 0) doreceivedsfwarning = true; @@ -1630,7 +1663,7 @@ void DebugReader::run() bool errorOccurred = false; QString cmd = mDebuggerPath; // QString arguments = "--annotate=2"; - QString arguments = "--annotate=2 --silent"; + QString arguments = "--interpret=mi --silent"; QString workingDir = QFileInfo(mDebuggerPath).path(); mProcess = new QProcess(); @@ -1680,7 +1713,8 @@ void DebugReader::run() break; readed = mProcess->readAll(); buffer += readed; - if (getLastAnnotation(buffer) == AnnotationType::TPrompt) { + + if ( readed.endsWith("\r\n")&& outputTerminated(buffer)) { mOutput = QString::fromUtf8(buffer); processDebugOutput(); buffer.clear(); diff --git a/RedPandaIDE/debugger.h b/RedPandaIDE/debugger.h index 5e88a14a..bef2d704 100644 --- a/RedPandaIDE/debugger.h +++ b/RedPandaIDE/debugger.h @@ -305,6 +305,7 @@ private: AnnotationType getAnnotation(const QString& s); AnnotationType getLastAnnotation(const QByteArray& text); AnnotationType getNextAnnotation(); + bool outputTerminated(QByteArray& text); QString getNextFilledLine(); QString getNextLine(); QString getNextWord(); @@ -372,6 +373,8 @@ private: bool doupdatelocal; bool mStop; + + int mOutputLine; friend class Debugger; // QThread interface protected: diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index c8d2c8ef..2a891ef1 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -1296,13 +1296,14 @@ void MainWindow::debug() if (!mDebugger->start()) return; filePath.replace('\\','/'); - mDebugger->sendCommand("set","host charset UTF-8"); - mDebugger->sendCommand("file", '"' + filePath + '"'); + mDebugger->sendCommand("-gdb-set","mi-async on"); + mDebugger->sendCommand("-gdb-set","host-charset UTF-8"); + mDebugger->sendCommand("-file-exec-and-symbols", '"' + filePath + '"'); if (mProject->options().type == ProjectType::DynamicLib) { QString host =mProject->options().hostApplication; host.replace('\\','/'); - mDebugger->sendCommand("exec-file", '"' + host + '"'); + mDebugger->sendCommand("-file-exec-file", '"' + host + '"'); } includeOrSkipDirs(mProject->options().includes, @@ -1375,7 +1376,9 @@ void MainWindow::debug() mDebugger->setUseUTF8(e->fileEncoding() == ENCODING_UTF8 || e->fileEncoding() == ENCODING_UTF8_BOM); if (!mDebugger->start()) return; - mDebugger->sendCommand("file", QString("\"%1\"").arg(debugFile.filePath().replace('\\','/'))); + mDebugger->sendCommand("-gdb-set","mi-async on"); + mDebugger->sendCommand("-gdb-set","host-charset UTF-8"); + mDebugger->sendCommand("-file-exec-and-symbols", QString("\"%1\"").arg(debugFile.filePath().replace('\\','/'))); } } break; @@ -1406,40 +1409,37 @@ void MainWindow::debug() mDebugger->sendAllBreakpointsToDebugger(); // Run the debugger - mDebugger->sendCommand("set", "width 0"); // don't wrap output, very annoying - mDebugger->sendCommand("set", "new-console on"); - mDebugger->sendCommand("set", "confirm off"); - mDebugger->sendCommand("set", "print repeats 0"); // don't repeat elements - mDebugger->sendCommand("set", "print elements 0"); // don't limit elements - mDebugger->sendCommand("cd", excludeTrailingPathDelimiter(debugFile.path())); // restore working directory + mDebugger->sendCommand("-gdb-set", "width 0"); // don't wrap output, very annoying + mDebugger->sendCommand("-gdb-set", "new-console on"); + mDebugger->sendCommand("-gdb-set", "confirm off"); + mDebugger->sendCommand("-gdb-set", "print repeats 0"); // don't repeat elements + mDebugger->sendCommand("-gdb-set", "print elements 0"); // don't limit elements + mDebugger->sendCommand("-environment-cd", excludeTrailingPathDelimiter(debugFile.path())); // restore working directory if (!debugInferiorhasBreakpoint()) { - QString params; switch(getCompileTarget()) { case CompileTarget::None: return; case CompileTarget::File: - mDebugger->sendCommand("start",params); + mDebugger->sendCommand("-exec-run", "--start"); mDebugger->updateDebugInfo(); break; case CompileTarget::Project: - params = ""; - mDebugger->sendCommand("start",params); + mDebugger->sendCommand("-exec-run", "--start"); mDebugger->updateDebugInfo(); break; default: break; } } else { - QString params; switch(getCompileTarget()) { case CompileTarget::None: return; case CompileTarget::File: - mDebugger->sendCommand("run",params); + mDebugger->sendCommand("-exec-run",""); mDebugger->updateDebugInfo(); break; case CompileTarget::Project: - mDebugger->sendCommand("run",params); + mDebugger->sendCommand("-exec-run",""); mDebugger->updateDebugInfo(); break; default: @@ -1617,13 +1617,13 @@ void MainWindow::includeOrSkipDirs(const QStringList &dirs, bool skip) foreach (QString dir,dirs) { QString dirName = dir.replace('\\','/'); if (skip) { - mDebugger->sendCommand( - "skip", - QString("-gfi \"%1/%2\"") - .arg(dirName,"*.*")); +// mDebugger->sendCommand( +// "skip", +// QString("-gfi \"%1/%2\"") +// .arg(dirName,"*.*")); } else { mDebugger->sendCommand( - "dir", + "-environment-directory", QString("\"%1\"").arg(dirName)); } } @@ -3932,7 +3932,7 @@ void MainWindow::on_actionStep_Over_triggered() if (mDebugger->executing()) { //WatchView.Items.BeginUpdate(); mDebugger->invalidateAllVars(); - mDebugger->sendCommand("next", ""); + mDebugger->sendCommand("-exec-next", ""); mDebugger->updateDebugInfo(); mDebugger->refreshWatchVars(); } @@ -3943,7 +3943,7 @@ void MainWindow::on_actionStep_Into_triggered() if (mDebugger->executing()) { //WatchView.Items.BeginUpdate(); mDebugger->invalidateAllVars(); - mDebugger->sendCommand("step", ""); + mDebugger->sendCommand("-exec-step", ""); mDebugger->updateDebugInfo(); mDebugger->refreshWatchVars(); } @@ -3955,7 +3955,7 @@ void MainWindow::on_actionStep_Out_triggered() if (mDebugger->executing()) { //WatchView.Items.BeginUpdate(); mDebugger->invalidateAllVars(); - mDebugger->sendCommand("finish", ""); + mDebugger->sendCommand("-exec-finish", ""); mDebugger->updateDebugInfo(); mDebugger->refreshWatchVars(); } @@ -3969,8 +3969,8 @@ void MainWindow::on_actionRun_To_Cursor_triggered() if (e!=nullptr) { //WatchView.Items.BeginUpdate(); mDebugger->invalidateAllVars(); - mDebugger->sendCommand("tbreak", QString(" %1").arg(e->caretY())); - mDebugger->sendCommand("continue", ""); + mDebugger->sendCommand("-break-insert", QString("-t --line %1").arg(e->caretY())); + mDebugger->sendCommand("-exec-continue", ""); mDebugger->updateDebugInfo(); mDebugger->refreshWatchVars(); } @@ -3983,7 +3983,7 @@ void MainWindow::on_actionContinue_triggered() if (mDebugger->executing()) { //WatchView.Items.BeginUpdate(); mDebugger->invalidateAllVars(); - mDebugger->sendCommand("continue", ""); + mDebugger->sendCommand("-exec-continue", ""); mDebugger->updateDebugInfo(); mDebugger->refreshWatchVars(); } @@ -4044,7 +4044,7 @@ void MainWindow::onDebugMemoryAddressInput() if (!s.isEmpty()) { connect(mDebugger, &Debugger::memoryExamineReady, this, &MainWindow::onMemoryExamineReady); - mDebugger->sendCommand("x/64bx",s,false); + mDebugger->sendCommand("-data-read-memory/64bx",s,false); } } From 71f5a7c056624a36d658fc2dc0f6fc4f6616fc47 Mon Sep 17 00:00:00 2001 From: "royqh1979@gmail.com" Date: Wed, 10 Nov 2021 12:57:18 +0800 Subject: [PATCH 02/32] work save --- RedPandaIDE/debugger.cpp | 30 ++++++++++++++++++++---------- RedPandaIDE/debugger.h | 6 +++--- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index 4cd44a40..5f77e1ab 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -1159,7 +1159,16 @@ AnnotationType DebugReader::peekNextAnnotation() return result; } -void DebugReader::processDebugOutput() +void DebugReader::processResultRecord(const QString &line) +{ + if (line.startsWith("^exit")) { + doprocessexited = true; + return; + } + +} + +void DebugReader::processDebugOutput(const QString& debugOutput) { // Only update once per update at most //WatchView.Items.BeginUpdate; @@ -1186,13 +1195,11 @@ void DebugReader::processDebugOutput() doupdatecpuwindow = false; doreceivedsfwarning = false; - QStringList lines = TextToLines(mOutput); + QStringList lines = TextToLines(debugOutput); - mOutputLine = 0; - while (mOutputLine=0) { + QString result = line.mid(pos+1); + processResult(result); + } + return ; + } + if (line.startsWith("^connected")) { + //TODO: connected to remote target return; } - } void DebugReader::processDebugOutput(const QString& debugOutput) @@ -1181,6 +1263,8 @@ void DebugReader::processDebugOutput(const QString& debugOutput) emit parseStarted(); + mConsoleOutput.clear(); + //try dobacktraceready = false; @@ -1189,7 +1273,6 @@ void DebugReader::processDebugOutput(const QString& debugOutput) doevalready = false; doupdatememoryview = false; doupdatelocal = false; - doprocessexited = false; doupdateexecution = false; doreceivedsignal = false; doupdatecpuwindow = false; @@ -1205,14 +1288,17 @@ void DebugReader::processDebugOutput(const QString& debugOutput) } switch (line[0].unicode()) { case '~': // console stream output + processConsoleOutput(line); + break; case '@': // target stream output case '&': // log stream output - //todo: process console stream output break; case '^': // result record processResultRecord(line); break; case '*': // exec async output + processExecAsyncRecord(line); + break; case '+': // status async output case '=': // notify async output break; @@ -1522,25 +1608,6 @@ void DebugReader::runNextCmd() } } -void DebugReader::skipSpaces() -{ - while (mIndex < mOutput.length() && - (mOutput[mIndex]=='\t' || mOutput[mIndex]==' ')) - mIndex++; -} - -void DebugReader::skipToAnnotation() -{ - // Walk up to the next annotation - while (mIndex < mOutput.length() && - (mOutput[mIndex]!=26)) - mIndex++; - // Crawl through the remaining ->'s - while (mIndex < mOutput.length() && - (mOutput[mIndex]==26)) - mIndex++; -} - QStringList DebugReader::tokenize(const QString &s) { QStringList result; @@ -1637,6 +1704,25 @@ QStringList DebugReader::tokenize(const QString &s) return result; } +QString DebugReader::removeToken(const QString &line) +{ + int p=0; + while (pstart(); mProcess->waitForStarted(5000); mStartSemaphore.release(1); - while (true) { mProcess->waitForFinished(1); if (mProcess->state()!=QProcess::Running) { diff --git a/RedPandaIDE/debugger.h b/RedPandaIDE/debugger.h index 7be47f6c..741c658f 100644 --- a/RedPandaIDE/debugger.h +++ b/RedPandaIDE/debugger.h @@ -18,27 +18,6 @@ enum class DebugCommandSource { Other }; -enum class AnnotationType { - TPrePrompt, TPrompt, TPostPrompt, - TSource, - TDisplayBegin, TDisplayEnd, - TDisplayExpression, - TFrameSourceFile, TFrameSourceBegin, TFrameSourceLine, TFrameFunctionName, TFrameWhere, - TFrameArgs, - TFrameBegin, TFrameEnd, - TErrorBegin, TErrorEnd, - TArrayBegin, TArrayEnd, - TElt, TEltRep, TEltRepEnd, - TExit, - TSignal, TSignalName, TSignalNameEnd, TSignalString, TSignalStringEnd, - TValueHistoryValue, TValueHistoryBegin, TValueHistoryEnd, - TArgBegin, TArgEnd, TArgValue, TArgNameEnd, - TFieldBegin, TFieldEnd, TFieldValue, TFieldNameEnd, - TInfoReg, TInfoAsm, - TUnknown, TEOF, - TLocal, TParam, TMemory -}; - struct DebugCommand{ QString command; QString params; @@ -284,10 +263,16 @@ public: void stopDebug(); bool commandRunning(); + bool waitStart(); bool invalidateAllVars() const; void setInvalidateAllVars(bool invalidateAllVars); + bool inferiorPaused() const; + + bool processExited() const; + + signals: void parseStarted(); void invalidateAllVars(); @@ -301,15 +286,7 @@ signals: void cmdFinished(); private: void clearCmdQueue(); - bool findAnnotation(AnnotationType annotation); - AnnotationType getAnnotation(const QString& s); - AnnotationType getLastAnnotation(const QByteArray& text); - AnnotationType getNextAnnotation(); bool outputTerminated(QByteArray& text); - QString getNextFilledLine(); - QString getNextLine(); - QString getNextWord(); - QString getRemainingLine(); void handleDisassembly(); void handleDisplay(); void handleError(); @@ -323,8 +300,11 @@ private: void handleSignal(); void handleSource(); void handleValueHistoryValue(); - AnnotationType peekNextAnnotation(); + void processConsoleOutput(const QString& line); + void processResult(const QString& result); + void processExecAsyncRecord(const QString& line); + void processError(const QString& errorLine); void processResultRecord(const QString& line); void processDebugOutput(const QString& debugOutput); QString processEvalOutput(); @@ -333,6 +313,7 @@ private: void skipSpaces(); void skipToAnnotation(); QStringList tokenize(const QString& s); + QString removeToken(const QString& line); private: Debugger *mDebugger; QString mDebuggerPath; @@ -365,7 +346,6 @@ private: bool dodisassemblerready; bool doregistersready; bool doevalready; - bool doprocessexited; bool doupdatecpuwindow; bool doupdateexecution; bool doreceivedsignal; @@ -373,9 +353,11 @@ private: bool doupdatememoryview; bool doupdatelocal; - bool mStop; + bool mInferiorPaused; + bool mProcessExited; + QStringList mConsoleOutput; - friend class Debugger; + bool mStop; // QThread interface protected: void run() override; diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 2a891ef1..36672c4c 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -1296,7 +1296,6 @@ void MainWindow::debug() if (!mDebugger->start()) return; filePath.replace('\\','/'); - mDebugger->sendCommand("-gdb-set","mi-async on"); mDebugger->sendCommand("-gdb-set","host-charset UTF-8"); mDebugger->sendCommand("-file-exec-and-symbols", '"' + filePath + '"'); @@ -1376,7 +1375,6 @@ void MainWindow::debug() mDebugger->setUseUTF8(e->fileEncoding() == ENCODING_UTF8 || e->fileEncoding() == ENCODING_UTF8_BOM); if (!mDebugger->start()) return; - mDebugger->sendCommand("-gdb-set","mi-async on"); mDebugger->sendCommand("-gdb-set","host-charset UTF-8"); mDebugger->sendCommand("-file-exec-and-symbols", QString("\"%1\"").arg(debugFile.filePath().replace('\\','/'))); } From e54d734252f1c66b58fa314b8a1e5b0d247839fe Mon Sep 17 00:00:00 2001 From: "royqh1979@gmail.com" Date: Wed, 10 Nov 2021 22:00:01 +0800 Subject: [PATCH 04/32] work save --- RedPandaIDE/debugger.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index b2b23d05..dca0ab3b 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -1708,9 +1708,15 @@ QString DebugReader::removeToken(const QString &line) { int p=0; while (p'9') { + break; + } + p++; } + if (p Date: Fri, 12 Nov 2021 10:51:00 +0800 Subject: [PATCH 05/32] work save --- RedPandaIDE/RedPandaIDE.pro | 2 + RedPandaIDE/compiler/executablerunner.cpp | 2 +- RedPandaIDE/debugger.cpp | 60 +++++++++------ RedPandaIDE/debugger.h | 22 +++--- RedPandaIDE/editor.cpp | 8 +- RedPandaIDE/gdbmiresultparser.cpp | 14 ++++ RedPandaIDE/gdbmiresultparser.h | 39 ++++++++++ RedPandaIDE/mainwindow.cpp | 4 +- RedPandaIDE/parser/cpppreprocessor.cpp | 2 +- RedPandaIDE/problems/problemcasevalidator.cpp | 4 +- RedPandaIDE/project.cpp | 8 +- RedPandaIDE/qsynedit/SynEdit.cpp | 14 ++-- RedPandaIDE/qsynedit/TextBuffer.cpp | 8 +- RedPandaIDE/utils.cpp | 73 ++++++++++++++----- RedPandaIDE/utils.h | 30 ++++---- RedPandaIDE/widgets/qconsole.cpp | 2 +- 16 files changed, 204 insertions(+), 88 deletions(-) create mode 100644 RedPandaIDE/gdbmiresultparser.cpp create mode 100644 RedPandaIDE/gdbmiresultparser.h diff --git a/RedPandaIDE/RedPandaIDE.pro b/RedPandaIDE/RedPandaIDE.pro index c3592332..33da8b50 100644 --- a/RedPandaIDE/RedPandaIDE.pro +++ b/RedPandaIDE/RedPandaIDE.pro @@ -25,6 +25,7 @@ SOURCES += \ compiler/ojproblemcasesrunner.cpp \ compiler/projectcompiler.cpp \ compiler/runner.cpp \ + gdbmiresultparser.cpp \ platform.cpp \ compiler/compiler.cpp \ compiler/compilermanager.cpp \ @@ -154,6 +155,7 @@ HEADERS += \ compiler/runner.h \ compiler/stdincompiler.h \ cpprefacter.h \ + gdbmiresultparser.h \ parser/cppparser.h \ parser/cpppreprocessor.h \ parser/cpptokenizer.h \ diff --git a/RedPandaIDE/compiler/executablerunner.cpp b/RedPandaIDE/compiler/executablerunner.cpp index 72ed47c1..8c050ef9 100644 --- a/RedPandaIDE/compiler/executablerunner.cpp +++ b/RedPandaIDE/compiler/executablerunner.cpp @@ -93,7 +93,7 @@ void ExecutableRunner::run() process.start(); process.waitForStarted(5000); if (process.state()==QProcess::Running && redirectInput()) { - process.write(ReadFileToByteArray(redirectInputFilename())); + process.write(readFileToByteArray(redirectInputFilename())); process.closeWriteChannel(); } while (true) { diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index dca0ab3b..58816a66 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -15,6 +15,7 @@ #include #include #include +#include Debugger::Debugger(QObject *parent) : QObject(parent) { @@ -485,7 +486,7 @@ void Debugger::syncFinishedParsing() pMainWindow->addDebugOutput(""); pMainWindow->addDebugOutput(""); } else { - QStringList strList = TextToLines(mReader->mOutput); + QStringList strList = textToLines(mReader->mOutput); QStringList outStrList; bool addToLastLine=false; for (int i=0;iname = s.mid(0,x); s.remove(0,x); // Remove spaces - s = TrimLeft(s); + s = trimLeft(s); // Cut hex value from 1 to first tab x = s.indexOf('\t'); @@ -1075,7 +1076,7 @@ void DebugReader::handleRegisters() x = s.indexOf(' '); reg->hexValue = s.mid(0,x); s.remove(0,x); // delete tab too - s = TrimLeft(s); + s = trimLeft(s); // Remaining part contains decimal value reg->decValue = s; @@ -1120,7 +1121,7 @@ void DebugReader::handleSignal() void DebugReader::handleSource() { // source filename:line:offset:beg/middle/end:addr - QString s = TrimLeft(getRemainingLine()); + QString s = trimLeft(getRemainingLine()); // remove offset, beg/middle/end, address for (int i=0;i<3;i++) { @@ -1151,18 +1152,18 @@ void DebugReader::handleValueHistoryValue() doevalready = true; } -void DebugReader::processConsoleOutput(const QString& line) +void DebugReader::processConsoleOutput(const QByteArray& line) { if (line.length()>3 && line.startsWith("~\"") && line.endsWith("\"")) { - mConsoleOutput.append(line.mid(2,line.length()-3)); + mConsoleOutput.append(QString::fromLocal8Bit(line.mid(2,line.length()-3))); } } -void DebugReader::processResult(const QString &result) +void DebugReader::processResult(const QByteArray &result) { int pos = result.indexOf('='); - QString name = result.mid(0,pos); - QString value = result.mid(pos+1); + QByteArray name = result.mid(0,pos); + QByteArray value = result.mid(pos+1); if (name == "bkpt") { // info about breakpoint handleBreakpoint(value); @@ -1220,12 +1221,12 @@ void DebugReader::processExecAsyncRecord(const QString &line) } } -void DebugReader::processError(const QString &errorLine) +void DebugReader::processError(const QByteArray &errorLine) { - //todo + mConsoleOutput.append(QString::fromLocal8Bit(errorLine)); } -void DebugReader::processResultRecord(const QString &line) +void DebugReader::processResultRecord(const QByteArray &line) { if (line.startsWith("^exit")) { mProcessExited = true; @@ -1239,7 +1240,7 @@ void DebugReader::processResultRecord(const QString &line) || line.startsWith("^running")) { int pos = line.indexOf(','); if (pos>=0) { - QString result = line.mid(pos+1); + QByteArray result = line.mid(pos+1); processResult(result); } return ; @@ -1250,7 +1251,7 @@ void DebugReader::processResultRecord(const QString &line) } } -void DebugReader::processDebugOutput(const QString& debugOutput) +void DebugReader::processDebugOutput(const QByteArray& debugOutput) { // Only update once per update at most //WatchView.Items.BeginUpdate; @@ -1278,15 +1279,15 @@ void DebugReader::processDebugOutput(const QString& debugOutput) doupdatecpuwindow = false; doreceivedsfwarning = false; - QStringList lines = TextToLines(debugOutput); + QList lines = splitByteArrayToLines(debugOutput); for (int i=0;i=2 && highlighter()->isLastLineCommentNotFinished( lines()->ranges(caretY()-2).state)) { - s=TrimLeft(lineText()); + s=trimLeft(lineText()); if (s.startsWith("* ")) { handled = true; int right = lines()->getString(caretY()-1).length()-caretX(); @@ -2095,7 +2095,7 @@ void Editor::insertCodeSnippet(const QString &code) auto action = finally([this]{ endUpdate(); }); - QStringList sl = TextToLines(parseMacros(code)); + QStringList sl = textToLines(parseMacros(code)); int lastI=0; int spaceCount = GetLeftSpacing( leftSpaces(lineText()),true).length(); @@ -2149,7 +2149,7 @@ void Editor::insertCodeSnippet(const QString &code) } BufferCoord cursorPos = caretXY(); - QString s = LinesToText(newSl); + QString s = linesToText(newSl); // if EndsStr(#13#10,s) then // Delete(s,Length(s)-1,2) // else if EndsStr(#10, s) then diff --git a/RedPandaIDE/gdbmiresultparser.cpp b/RedPandaIDE/gdbmiresultparser.cpp new file mode 100644 index 00000000..861b9253 --- /dev/null +++ b/RedPandaIDE/gdbmiresultparser.cpp @@ -0,0 +1,14 @@ +#include "gdbmiresultparser.h" + +#include + +GDBMIResultParser::GDBMIResultParser() +{ + +} + +bool GDBMIResultParser::parse(const QByteArray &record, GDBMIResultType &type, void **pResult) +{ + QList tokens; + tokens = tokenize(record); +} diff --git a/RedPandaIDE/gdbmiresultparser.h b/RedPandaIDE/gdbmiresultparser.h new file mode 100644 index 00000000..3950388e --- /dev/null +++ b/RedPandaIDE/gdbmiresultparser.h @@ -0,0 +1,39 @@ +#ifndef GDBMIRESULTPARSER_H +#define GDBMIRESULTPARSER_H + +#include +#include + + +enum class GDBMIResultType { + Breakpoint, + BreakpointTable, + FrameStack, + LocalVariables, + Locals, + Frame, + Disassembly, + Evaluation, + RegisterNames, + RegisterValues, + Memory +}; + + +class GDBMIResultParser +{ + struct ParseValue { + private: + QVariant mData; + }; + + struct ParseObject { + QHash props; + }; + +public: + GDBMIResultParser(); + bool parse(const QByteArray& record, GDBMIResultType& type, void** pResult); +}; + +#endif // GDBMIRESULTPARSER_H diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 902c83a9..3c633bdb 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -5099,8 +5099,8 @@ void MainWindow::updateProblemCaseOutput(POJProblemCase problemCase) ui->txtProblemCaseOutput->clear(); ui->txtProblemCaseOutput->setText(problemCase->output); if (problemCase->testState == ProblemCaseTestState::Failed) { - QStringList output = TextToLines(problemCase->output); - QStringList expected = TextToLines(problemCase->expected); + QStringList output = textToLines(problemCase->output); + QStringList expected = textToLines(problemCase->expected); for (int i=0;i=expected.count() || output[i]!=expected[i]) { QTextBlock block = ui->txtProblemCaseOutput->document()->findBlockByLineNumber(i); diff --git a/RedPandaIDE/parser/cpppreprocessor.cpp b/RedPandaIDE/parser/cpppreprocessor.cpp index b45b1fbb..fc13cb1b 100644 --- a/RedPandaIDE/parser/cpppreprocessor.cpp +++ b/RedPandaIDE/parser/cpppreprocessor.cpp @@ -680,7 +680,7 @@ void CppPreprocessor::openInclude(const QString &fileName, QStringList bufferedT if (!bufferedText.isEmpty()) { parsedFile->buffer = bufferedText; } else { - parsedFile->buffer = ReadFileToLines(fileName); + parsedFile->buffer = readFileToLines(fileName); } } } else { diff --git a/RedPandaIDE/problems/problemcasevalidator.cpp b/RedPandaIDE/problems/problemcasevalidator.cpp index b3a70552..112d97a3 100644 --- a/RedPandaIDE/problems/problemcasevalidator.cpp +++ b/RedPandaIDE/problems/problemcasevalidator.cpp @@ -10,8 +10,8 @@ bool ProblemCaseValidator::validate(POJProblemCase problemCase) { if (!problemCase) return false; - QStringList output = TextToLines(problemCase->output); - QStringList expected = TextToLines(problemCase->expected); + QStringList output = textToLines(problemCase->output); + QStringList expected = textToLines(problemCase->expected); if (output.count()!=expected.count()) return false; for (int i=0;i 3) { - StringsToFile(contents,rcFile); + stringsToFile(contents,rcFile); mOptions.privateResource = extractRelativePath(directory(), rcFile); } else { if (fileExists(rcFile)) @@ -1061,7 +1061,7 @@ void Project::buildPrivateResource(bool forceSave) content.append(" "); content.append(""); content.append(""); - StringsToFile(content,executable() + ".Manifest"); + stringsToFile(content,executable() + ".Manifest"); } else if (fileExists(executable() + ".Manifest")) QFile::remove(executable() + ".Manifest"); @@ -1107,7 +1107,7 @@ void Project::buildPrivateResource(bool forceSave) .arg(mOptions.versionInfo.productVersion)); contents.append(""); contents.append("#endif /*" + def + "*/"); - StringsToFile(contents,hFile); + stringsToFile(contents,hFile); } void Project::checkProjectFileForUpdate(SimpleIni &ini) @@ -1757,7 +1757,7 @@ bool ProjectUnit::save() if (!mEditor && !fileExists(mFileName)) { // file is neither open, nor saved QStringList temp; - StringsToFile(temp,mFileName); + stringsToFile(temp,mFileName); } else if (mEditor && mEditor->modified()) { result = mEditor->save(); } diff --git a/RedPandaIDE/qsynedit/SynEdit.cpp b/RedPandaIDE/qsynedit/SynEdit.cpp index 3497183a..024365ef 100644 --- a/RedPandaIDE/qsynedit/SynEdit.cpp +++ b/RedPandaIDE/qsynedit/SynEdit.cpp @@ -1785,7 +1785,7 @@ void SynEdit::doDeleteLastChar() mLines->deleteAt(mCaretY); doLinesDeleted(mCaretY+1, 1); if (mOptions.testFlag(eoTrimTrailingSpaces)) - Temp = TrimRight(Temp); + Temp = trimRight(Temp); setLineText(lineText() + Temp); helper = lineBreak(); //"/r/n" } @@ -2119,7 +2119,7 @@ void SynEdit::insertLine(bool moveCaret) rightLineText,mOptions.testFlag(eoAutoIndent) && notInComment); if (mOptions.testFlag(eoAutoIndent)) { - rightLineText=TrimLeft(rightLineText); + rightLineText=trimLeft(rightLineText); } QString indentSpacesForRightLineText = GetLeftSpacing(indentSpaces,true); mLines->insert(mCaretY, indentSpacesForRightLineText+rightLineText); @@ -2632,7 +2632,7 @@ void SynEdit::doAddChar(QChar AChar) if (line.length() < oldCaretX) { int indentSpaces = calcIndentSpaces(oldCaretY,line+":", true); if (indentSpaces != leftSpaces(line)) { - QString temp = GetLeftSpacing(indentSpaces,true) + TrimLeft(line); + QString temp = GetLeftSpacing(indentSpaces,true) + trimLeft(line); int i = temp.length(); mLines->putString(oldCaretY-1,temp); internalSetCaretXY(BufferCoord{i+1,oldCaretY}); @@ -4941,7 +4941,7 @@ void SynEdit::doLinesInserted(int firstLine, int count) void SynEdit::properSetLine(int ALine, const QString &ALineText) { if (mOptions.testFlag(eoTrimTrailingSpaces)) - mLines->putString(ALine,TrimRight(ALineText)); + mLines->putString(ALine,trimRight(ALineText)); else mLines->putString(ALine,ALineText); } @@ -5047,7 +5047,7 @@ int SynEdit::insertTextByNormalMode(const QString &Value) int Result = 0; sLeftSide = lineText().mid(0, mCaretX - 1); if (mCaretX - 1 > sLeftSide.length()) { - if (StringIsBlank(sLeftSide)) + if (stringIsBlank(sLeftSide)) sLeftSide = GetLeftSpacing(displayX() - 1, true); else sLeftSide += QString(mCaretX - 1 - sLeftSide.length(),' '); @@ -5063,7 +5063,7 @@ int SynEdit::insertTextByNormalMode(const QString &Value) Start = 0; P = GetEOL(Value,Start); if (PtoUnicode(line.constData(),line.length(),&state); if (state.invalidChars>0) { needReread = true; break; } - addItem(TrimRight(newLine)); + addItem(trimRight(newLine)); } if (file.atEnd()){ break; @@ -579,7 +579,7 @@ void SynEditStringList::loadFromFile(const QString& filename, const QByteArray& QString line; internalClear(); while (textStream.readLineInto(&line)) { - addItem(TrimRight(line)); + addItem(trimRight(line)); } emit inserted(0,mList.count()); } diff --git a/RedPandaIDE/utils.cpp b/RedPandaIDE/utils.cpp index 4cb6e285..0c66cc6c 100644 --- a/RedPandaIDE/utils.cpp +++ b/RedPandaIDE/utils.cpp @@ -291,25 +291,25 @@ QString toLocalPath(const QString &filename) return newPath; } -QStringList TextToLines(const QString &text) +QStringList textToLines(const QString &text) { QTextStream stream(&((QString&)text),QIODevice::ReadOnly); - return ReadStreamToLines(&stream); + return readStreamToLines(&stream); } -QStringList ReadFileToLines(const QString& fileName, QTextCodec* codec) +QStringList readFileToLines(const QString& fileName, QTextCodec* codec) { QFile file(fileName); if (file.open(QFile::ReadOnly)) { QTextStream stream(&file); stream.setCodec(codec); stream.setAutoDetectUnicode(false); - return ReadStreamToLines(&stream); + return readStreamToLines(&stream); } return QStringList(); } -QStringList ReadStreamToLines(QTextStream *stream) +QStringList readStreamToLines(QTextStream *stream) { QStringList list; QString s; @@ -319,7 +319,7 @@ QStringList ReadStreamToLines(QTextStream *stream) return list; } -void ReadStreamToLines(QTextStream *stream, +void readStreamToLines(QTextStream *stream, LineProcessFunc lineFunc) { QString s; @@ -328,20 +328,20 @@ void ReadStreamToLines(QTextStream *stream, } } -void TextToLines(const QString &text, LineProcessFunc lineFunc) +void textToLines(const QString &text, LineProcessFunc lineFunc) { QTextStream stream(&((QString&)text),QIODevice::ReadOnly); - ReadStreamToLines(&stream,lineFunc); + readStreamToLines(&stream,lineFunc); } -void ReadFileToLines(const QString &fileName, QTextCodec *codec, LineProcessFunc lineFunc) +void readFileToLines(const QString &fileName, QTextCodec *codec, LineProcessFunc lineFunc) { QFile file(fileName); if (file.open(QFile::ReadOnly)) { QTextStream stream(&file); stream.setCodec(codec); stream.setAutoDetectUnicode(false); - ReadStreamToLines(&stream, lineFunc); + readStreamToLines(&stream, lineFunc); } } @@ -401,7 +401,7 @@ void inflateRect(QRect &rect, int dx, int dy) rect.setBottom(rect.bottom()+dy); } -QString TrimRight(const QString &s) +QString trimRight(const QString &s) { if (s.isEmpty()) return s; @@ -417,7 +417,7 @@ QString TrimRight(const QString &s) } } -bool StringIsBlank(const QString &s) +bool stringIsBlank(const QString &s) { for (QChar ch:s) { if (ch != ' ' && ch != '\t') @@ -426,7 +426,7 @@ bool StringIsBlank(const QString &s) return true; } -QString TrimLeft(const QString &s) +QString trimLeft(const QString &s) { if (s.isEmpty()) return s; @@ -502,7 +502,7 @@ QString changeFileExt(const QString& filename, QString ext) } } -QStringList ReadFileToLines(const QString &fileName) +QStringList readFileToLines(const QString &fileName) { QFile file(fileName); if (file.size()<=0) @@ -539,7 +539,7 @@ QStringList ReadFileToLines(const QString &fileName) return result; } -void StringsToFile(const QStringList &list, const QString &fileName) +void stringsToFile(const QStringList &list, const QString &fileName) { QFile file(fileName); if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { @@ -748,7 +748,7 @@ QString fromByteArray(const QByteArray &s) return QString::fromLocal8Bit(s); } -QString LinesToText(const QStringList &lines) +QString linesToText(const QStringList &lines) { return lines.join("\n"); } @@ -831,7 +831,7 @@ void executeFile(const QString &fileName, const QString ¶ms, const QString & ); } -void StringToFile(const QString &str, const QString &fileName) +void stringToFile(const QString &str, const QString &fileName) { QFile file(fileName); if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { @@ -846,7 +846,7 @@ bool removeFile(const QString &filename) return file.remove(); } -QByteArray ReadFileToByteArray(const QString &fileName) +QByteArray readFileToByteArray(const QString &fileName) { QFile file(fileName); if (file.open(QFile::ReadOnly)) { @@ -893,3 +893,40 @@ bool readRegistry(HKEY key,const QByteArray& subKey, const QByteArray& name, QSt delete [] buffer; return true; } + +QList splitByteArrayToLines(const QByteArray &content) +{ + QList lines; + const char* p =content.constData(); + const char* end = p+content.length(); + const char* lineStart = p; + QByteArray line; + while (p<=end) { + char ch=*p; + switch(ch) { + case '\r': + line = QByteArray(lineStart, p-lineStart); + lines.append(line); + p++; + if (*p=='\n') + p++; + lineStart = p; + break; + case '\n': + line = QByteArray(lineStart, p-lineStart); + lines.append(line); + p++; + lineStart = p; + break; + default: + p++; + } + } + if (lineStart>end) { + lines.append(""); + } else { + line = QByteArray(lineStart, end-lineStart+1); + lines.append(line); + } + return lines; +} diff --git a/RedPandaIDE/utils.h b/RedPandaIDE/utils.h index 39fd41a5..7380e2f4 100644 --- a/RedPandaIDE/utils.h +++ b/RedPandaIDE/utils.h @@ -143,28 +143,30 @@ bool programHasConsole(const QString& filename); QString toLocalPath(const QString& filename); using LineProcessFunc = std::function; -QStringList ReadStreamToLines(QTextStream* stream); -void ReadStreamToLines(QTextStream* stream, LineProcessFunc lineFunc); +QStringList readStreamToLines(QTextStream* stream); +void readStreamToLines(QTextStream* stream, LineProcessFunc lineFunc); -QStringList TextToLines(const QString& text); -void TextToLines(const QString& text, LineProcessFunc lineFunc); -QString LinesToText(const QStringList& lines); +QStringList textToLines(const QString& text); +void textToLines(const QString& text, LineProcessFunc lineFunc); +QString linesToText(const QStringList& lines); + +QList splitByteArrayToLines(const QByteArray& content); QString parseMacros(const QString& s); -QStringList ReadFileToLines(const QString& fileName, QTextCodec* codec); -QStringList ReadFileToLines(const QString& fileName); -QByteArray ReadFileToByteArray(const QString& fileName); -void ReadFileToLines(const QString& fileName, QTextCodec* codec, LineProcessFunc lineFunc); -void StringsToFile(const QStringList& list, const QString& fileName); -void StringToFile(const QString& str, const QString& fileName); +QStringList readFileToLines(const QString& fileName, QTextCodec* codec); +QStringList readFileToLines(const QString& fileName); +QByteArray readFileToByteArray(const QString& fileName); +void readFileToLines(const QString& fileName, QTextCodec* codec, LineProcessFunc lineFunc); +void stringsToFile(const QStringList& list, const QString& fileName); +void stringToFile(const QString& str, const QString& fileName); void decodeKey(int combinedKey, int& key, Qt::KeyboardModifiers& modifiers); void inflateRect(QRect& rect, int delta); void inflateRect(QRect& rect, int dx, int dy); -QString TrimRight(const QString& s); -QString TrimLeft(const QString& s); -bool StringIsBlank(const QString& s); +QString trimRight(const QString& s); +QString trimLeft(const QString& s); +bool stringIsBlank(const QString& s); int compareFileModifiedTime(const QString& filename1, const QString& filename2); QByteArray getHTTPBody(const QByteArray& content); bool haveGoodContrast(const QColor& c1, const QColor &c2); diff --git a/RedPandaIDE/widgets/qconsole.cpp b/RedPandaIDE/widgets/qconsole.cpp index bc7b860d..e1d06ffa 100644 --- a/RedPandaIDE/widgets/qconsole.cpp +++ b/RedPandaIDE/widgets/qconsole.cpp @@ -147,7 +147,7 @@ void QConsole::addLine(const QString &line) void QConsole::addText(const QString &text) { - QStringList lst = TextToLines(text); + QStringList lst = textToLines(text); for (const QString& line:lst) { addLine(line); } From 83a794b9c2279c7e13dff0b6ca19407ecc082845 Mon Sep 17 00:00:00 2001 From: royqh1979 Date: Fri, 12 Nov 2021 22:42:51 +0800 Subject: [PATCH 06/32] work save --- RedPandaIDE/gdbmiresultparser.cpp | 283 +++++++++++++++++++++++++++++- RedPandaIDE/gdbmiresultparser.h | 58 +++++- 2 files changed, 330 insertions(+), 11 deletions(-) diff --git a/RedPandaIDE/gdbmiresultparser.cpp b/RedPandaIDE/gdbmiresultparser.cpp index 861b9253..0e3e23fa 100644 --- a/RedPandaIDE/gdbmiresultparser.cpp +++ b/RedPandaIDE/gdbmiresultparser.cpp @@ -2,13 +2,288 @@ #include +static GDBMIResultParser::ParseValue EMPTY_PARSE_VALUE; + GDBMIResultParser::GDBMIResultParser() { - + mResultTypes.insert("bkpt",GDBMIResultType::Breakpoint); + mResultTypes.insert("BreakpointTable",GDBMIResultType::BreakpointTable); + mResultTypes.insert("stack",GDBMIResultType::FrameStack); + mResultTypes.insert("variables", GDBMIResultType::LocalVariables); + mResultTypes.insert("frame",GDBMIResultType::Frame); + mResultTypes.insert("asm_insns",GDBMIResultType::Disassembly); + mResultTypes.insert("value",GDBMIResultType::Evaluation); + mResultTypes.insert("register-names",GDBMIResultType::RegisterNames); + mResultTypes.insert("register-values",GDBMIResultType::RegisterValues); + mResultTypes.insert("memory",GDBMIResultType::Memory); } -bool GDBMIResultParser::parse(const QByteArray &record, GDBMIResultType &type, void **pResult) +bool GDBMIResultParser::parse(const QByteArray &record, GDBMIResultType &type, ParseValue& value) { - QList tokens; - tokens = tokenize(record); + const char* p = record.data(); + QByteArray name; + bool result = parseNameAndValue(p,name,value); + if (!result) + return false; +// if (*p!=0) +// return false; + if (!mResultTypes.contains(name)) + return false; + type = mResultTypes[name]; + return true; } + +bool GDBMIResultParser::parseNameAndValue(char *&p, QByteArray &name, ParseValue &value) +{ + skipSpaces(p); + char* nameStart =p; + while (*p!=0 && isNameChar(*p)) { + p++; + } + if (*p==0) + return false; + skipSpaces(p); + if (*p!='=') + return false; + return parseValue(p,value); +} + +bool GDBMIResultParser::parseValue(char *&p, ParseValue &value) +{ + skipSpaces(p); + bool result; + switch (*p) { + case '{': { + ParseObject obj; + result = parseObject(p,obj); + value = obj; + break; + } + case '[': { + QList array; + result = parseArray(p,array); + value = array; + break; + } + case '"': { + QByteArray s; + result = parseStringValue(p,s); + value = s; + break; + } + default: + return false; + } + if (!result) + return false; + skipSpaces(p); + if (*p!=0 && *p!=',') + return false; + return true; +} + +bool GDBMIResultParser::parseStringValue(char *&p, QByteArray& stringValue) +{ + if (*p!='"') + return false; + p++; + char* valueStart = p; + while (*p!=0) { + if (*p == '"') { + break; + } else if (*p=='\\' && *(p+1)!=0) { + p+=2; + } else { + p++; + } + } + if (*p=='"') { + stringValue = QByteArray(valueStart,p-valueStart); + p++; //skip '"' + return true; + } + return false; +} + +bool GDBMIResultParser::parseObject(char *&p, ParseObject &obj) +{ + if (*p!='{') + return false; + p++; + + if (*p!='}') { + while (*p!=0) { + QByteArray propName; + ParseValue propValue; + bool result = parseNameAndValue(p,propName,propValue); + if (result) { + obj[propName]=propValue; + } else { + return false; + } + skipSpaces(p); + if (*p=='}') + break; + if (*p!=',') + return false; + p++; //skip ',' + skipSpaces(p); + } + } + if (*p=='}') { + p++; //skip '}' + return true; + } + return false; +} + +bool GDBMIResultParser::parseArray(char *&p, ParseValue &value) +{ + if (*p!='[') + return false; + p++; + QList array; + if (*p!=']') { + while (*p!=0) { + skipSpaces(p); + QObject obj; + bool result = parseObject(p,obj); + if (result) { + array.append(obj); + } else { + return false; + } + skipSpaces(p); + if (*p==']') + break; + if (*p!=',') + return false; + p++; //skip ',' + skipSpaces(p); + } + } + if (*p==']') { + value = array; + p++; //skip ']' + return true; + } + return false; +} + +bool GDBMIResultParser::isNameChar(char ch) +{ + if (ch=='-') + return true; + if (ch>='a' && ch<='z') + return true; + if (ch>='A' && ch<='Z') + return true; + return false; +} + +bool GDBMIResultParser::isSpaceChar(char ch) +{ + switch(ch) { + case ' ': + case '\t': + return true; + } + return false; +} + +void GDBMIResultParser::skipSpaces(char *&p) +{ + while (*p!=0 && isSpaceChar(*p)) + p++; +} + +const QString &GDBMIResultParser::ParseValue::value() const +{ + return mValue; +} + +const QList &GDBMIResultParser::ParseValue::array() const +{ + return mArray; +} + +const GDBMIResultParser::ParseObject &GDBMIResultParser::ParseValue::object() const +{ + return mObject; +} + +GDBMIResultParser::ParseValueType GDBMIResultParser::ParseValue::type() const +{ + return mType; +} + +GDBMIResultParser::ParseValue::ParseValue(): + mType(ParseValueType::NotAssigned) { + +} + +GDBMIResultParser::ParseValue::ParseValue(const QString &value): + mValue(value), + mType(ParseValueType::Value) +{ +} + +GDBMIResultParser::ParseValue::ParseValue(const PParseObject &object): + mObject(object), + mType(ParseValueType::Object) +{ +} + +GDBMIResultParser::ParseValue::ParseValue(const QList &array): + mArray(array), + mType(ParseValueType::Array) +{ +} + +void GDBMIResultParser::ParseValue::addObject(const PParseObject &object) +{ + Q_ASSERT(mType == ParseValueType::Array || mType == ParseValueType::NotAssigned); + mType = ParseValueType::Array; + mArray.append(object); +} + +GDBMIResultParser::ParseValue &GDBMIResultParser::ParseValue::operator=(const QString &value) +{ + Q_ASSERT(mType == ParseValueType::NotAssigned); + mType = ParseValueType::Value; + mValue = value; +} + +GDBMIResultParser::ParseValue &GDBMIResultParser::ParseValue::operator=(const ParseObject& object) +{ + Q_ASSERT(mType == ParseValueType::NotAssigned); + mType = ParseValueType::Object; + mObject = object; +} + +GDBMIResultParser::ParseValue &GDBMIResultParser::ParseValue::operator=(const QList& array) +{ + Q_ASSERT(mType == ParseValueType::NotAssigned); + mType = ParseValueType::Array; + mArray = array; +} + + +const GDBMIResultParser::ParseValue &GDBMIResultParser::ParseObject::operator[](const QByteArray &name) const +{ + if (mProps.contains(name)) + return mProps[name]; + return EMPTY_PARSE_VALUE; +} + +GDBMIResultParser::ParseObject &GDBMIResultParser::ParseObject::operator=(const ParseObject &object) +{ + mProps = object.mProps; +} + +GDBMIResultParser::ParseValue &GDBMIResultParser::ParseObject::operator[](const QByteArray &name) { + if (!mProps.contains(name)) + mProps[name]=ParseValue(); + return mProps[name]; +} + diff --git a/RedPandaIDE/gdbmiresultparser.h b/RedPandaIDE/gdbmiresultparser.h index 3950388e..0842134a 100644 --- a/RedPandaIDE/gdbmiresultparser.h +++ b/RedPandaIDE/gdbmiresultparser.h @@ -2,7 +2,7 @@ #define GDBMIRESULTPARSER_H #include -#include +#include enum class GDBMIResultType { @@ -22,18 +22,62 @@ enum class GDBMIResultType { class GDBMIResultParser { - struct ParseValue { - private: - QVariant mData; + enum class ParseValueType { + Value, + Object, + Array, + NotAssigned }; - struct ParseObject { - QHash props; + class ParseObject; + + class ParseValue { + public: + explicit ParseValue(); + explicit ParseValue(const QString& value); + explicit ParseValue(const ParseObject &object); + explicit ParseValue(const QList& array); + ParseValue(const ParseValue&) = delete; + void addObject(const PParseObject& object); + const QString &value() const; + QList &array() const; + const PParseObject &object() const; + ParseValueType type() const; + ParseValue& operator=(const QString& value); + ParseValue& operator=(const ParseObject& object); + ParseValue& operator=(const QList& array); + ParseValue& operator=(const ParseValue& value); + private: + QString mValue; + QList mArray; + ParseObject mObject; + ParseValueType mType; + }; + + using PParseValue = std::shared_ptr; + + class ParseObject { + const ParseValue& operator[](const QByteArray& name) const; + ParseValue& operator[](const QByteArray& name); + ParseObject& operator=(const ParseObject& object); + private: + QHash mProps; }; public: GDBMIResultParser(); - bool parse(const QByteArray& record, GDBMIResultType& type, void** pResult); + bool parse(const QByteArray& record, GDBMIResultType& type, ParseValue& value); +private: + bool parseNameAndValue(char* &p,QByteArray& name, ParseValue& value); + bool parseValue(char* &p, ParseValue& value); + bool parseStringValue(char*&p, QByteArray& stringValue); + bool parseObject(char*&p, ParseObject& obj); + bool parseArray(char*&p, QList& array); + void skipSpaces(char* &p); + bool isNameChar(char ch); + bool isSpaceChar(char ch); +private: + QHash mResultTypes; }; #endif // GDBMIRESULTPARSER_H From 3668378d7f6a1066d40027711fbe793a66eb1713 Mon Sep 17 00:00:00 2001 From: "royqh1979@gmail.com" Date: Sat, 13 Nov 2021 11:16:05 +0800 Subject: [PATCH 07/32] work save --- RedPandaIDE/gdbmiresultparser.cpp | 25 ++++++++++------------ RedPandaIDE/gdbmiresultparser.h | 35 +++++++++++++++++-------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/RedPandaIDE/gdbmiresultparser.cpp b/RedPandaIDE/gdbmiresultparser.cpp index 19521d55..218cc955 100644 --- a/RedPandaIDE/gdbmiresultparser.cpp +++ b/RedPandaIDE/gdbmiresultparser.cpp @@ -2,8 +2,6 @@ #include -static GDBMIResultParser::ParseValue EMPTY_PARSE_VALUE; - GDBMIResultParser::GDBMIResultParser() { mResultTypes.insert("bkpt",GDBMIResultType::Breakpoint); @@ -33,22 +31,23 @@ bool GDBMIResultParser::parse(const QByteArray &record, GDBMIResultType &type, P return true; } -bool GDBMIResultParser::parseNameAndValue(char *&p, QByteArray &name, ParseValue &value) +bool GDBMIResultParser::parseNameAndValue(const char *&p, QByteArray &name, ParseValue &value) { skipSpaces(p); - char* nameStart =p; + const char* nameStart =p; while (*p!=0 && isNameChar(*p)) { p++; } if (*p==0) return false; + name = QByteArray(nameStart,p-nameStart); skipSpaces(p); if (*p!='=') return false; return parseValue(p,value); } -bool GDBMIResultParser::parseValue(char *&p, ParseValue &value) +bool GDBMIResultParser::parseValue(const char *&p, ParseValue &value) { skipSpaces(p); bool result; @@ -82,12 +81,12 @@ bool GDBMIResultParser::parseValue(char *&p, ParseValue &value) return true; } -bool GDBMIResultParser::parseStringValue(char *&p, QByteArray& stringValue) +bool GDBMIResultParser::parseStringValue(const char *&p, QByteArray& stringValue) { if (*p!='"') return false; p++; - char* valueStart = p; + const char* valueStart = p; while (*p!=0) { if (*p == '"') { break; @@ -105,7 +104,7 @@ bool GDBMIResultParser::parseStringValue(char *&p, QByteArray& stringValue) return false; } -bool GDBMIResultParser::parseObject(char *&p, ParseObject &obj) +bool GDBMIResultParser::parseObject(const char *&p, ParseObject &obj) { if (*p!='{') return false; @@ -137,12 +136,11 @@ bool GDBMIResultParser::parseObject(char *&p, ParseObject &obj) return false; } -bool GDBMIResultParser::parseArray(char *&p, ParseValue &value) +bool GDBMIResultParser::parseArray(const char *&p, QList &array) { if (*p!='[') return false; p++; - QList array; if (*p!=']') { while (*p!=0) { skipSpaces(p); @@ -163,7 +161,6 @@ bool GDBMIResultParser::parseArray(char *&p, ParseValue &value) } } if (*p==']') { - value = array; p++; //skip ']' return true; } @@ -191,7 +188,7 @@ bool GDBMIResultParser::isSpaceChar(char ch) return false; } -void GDBMIResultParser::skipSpaces(char *&p) +void GDBMIResultParser::skipSpaces(const char *&p) { while (*p!=0 && isSpaceChar(*p)) p++; @@ -262,11 +259,11 @@ GDBMIResultParser::ParseValue &GDBMIResultParser::ParseValue::operator=(const QL } -const GDBMIResultParser::ParseValue &GDBMIResultParser::ParseObject::operator[](const QByteArray &name) const +const GDBMIResultParser::ParseValue GDBMIResultParser::ParseObject::operator[](const QByteArray &name) const { if (mProps.contains(name)) return mProps[name]; - return EMPTY_PARSE_VALUE; + return ParseValue(); } GDBMIResultParser::ParseObject &GDBMIResultParser::ParseObject::operator=(const ParseObject &object) diff --git a/RedPandaIDE/gdbmiresultparser.h b/RedPandaIDE/gdbmiresultparser.h index 3009fe96..b989d91e 100644 --- a/RedPandaIDE/gdbmiresultparser.h +++ b/RedPandaIDE/gdbmiresultparser.h @@ -2,8 +2,9 @@ #define GDBMIRESULTPARSER_H #include +#include #include -#include +#include enum class GDBMIResultType { @@ -23,6 +24,7 @@ enum class GDBMIResultType { class GDBMIResultParser { +public: enum class ParseValueType { Value, Object, @@ -30,7 +32,16 @@ class GDBMIResultParser NotAssigned }; - class ParseObject; + class ParseValue; + + class ParseObject { + public: + const ParseValue operator[](const QByteArray& name) const; + ParseValue& operator[](const QByteArray& name); + ParseObject& operator=(const ParseObject& object); + private: + QHash mProps; + }; class ParseValue { public: @@ -56,24 +67,16 @@ class GDBMIResultParser using PParseValue = std::shared_ptr; - class ParseObject { - const ParseValue& operator[](const QByteArray& name) const; - ParseValue& operator[](const QByteArray& name); - ParseObject& operator=(const ParseObject& object); - private: - QHash mProps; - }; - public: GDBMIResultParser(); bool parse(const QByteArray& record, GDBMIResultType& type, ParseValue& value); private: - bool parseNameAndValue(char* &p,QByteArray& name, ParseValue& value); - bool parseValue(char* &p, ParseValue& value); - bool parseStringValue(char*&p, QByteArray& stringValue); - bool parseObject(char*&p, ParseObject& obj); - bool parseArray(char*&p, QList& array); - void skipSpaces(char* &p); + bool parseNameAndValue(const char *&p,QByteArray& name, ParseValue& value); + bool parseValue(const char* &p, ParseValue& value); + bool parseStringValue(const char*&p, QByteArray& stringValue); + bool parseObject(const char*&p, ParseObject& obj); + bool parseArray(const char*&p, QList& array); + void skipSpaces(const char* &p); bool isNameChar(char ch); bool isSpaceChar(char ch); private: From 3f474a9db4f95677fa74eab0471eb989e311f020 Mon Sep 17 00:00:00 2001 From: "royqh1979@gmail.com" Date: Sat, 20 Nov 2021 07:53:39 +0800 Subject: [PATCH 08/32] work save --- RedPandaIDE/debugger.cpp | 27 +++++++++++++++++++-------- RedPandaIDE/debugger.h | 7 ++++++- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index 58816a66..a873db04 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -12,10 +12,6 @@ #include #include #include -#include -#include -#include -#include Debugger::Debugger(QObject *parent) : QObject(parent) { @@ -150,6 +146,7 @@ void Debugger::addBreakpoint(int line, const Editor* editor) void Debugger::addBreakpoint(int line, const QString &filename) { PBreakpoint bp=std::make_shared(); + bp->number = -1; bp->line = line; bp->filename = filename; bp->condition = ""; @@ -422,13 +419,12 @@ void Debugger::sendClearBreakpointCommand(int index) void Debugger::sendClearBreakpointCommand(PBreakpoint breakpoint) { // Debugger already running? Remove it from GDB - if (breakpoint && mExecuting) { + if (breakpoint && breakpoint->number>=0 && mExecuting) { //clear "filename":linenum QString filename = breakpoint->filename; filename.replace('\\','/'); - sendCommand("clear", - QString("\"%1\":%2").arg(filename) - .arg(breakpoint->line)); + sendCommand("-break-delete", + QString("%1").arg(breakpoint->number)); } } @@ -1162,6 +1158,18 @@ void DebugReader::processConsoleOutput(const QByteArray& line) void DebugReader::processResult(const QByteArray &result) { int pos = result.indexOf('='); + GDBMIResultParser parser; + GDBMIResultType resultType; + GDBMIResultParser::ParseValue parseValue; + bool parseOk = parser.parse(result,resultType,parseValue); + if (!parseOk) + return; + switch(resultType) { + case GDBMIResultType::Breakpoint: + handleBreakpoint(parseValue.object()); + return; + } + QByteArray name = result.mid(0,pos); QByteArray value = result.mid(pos+1); if (name == "bkpt") { @@ -1711,6 +1719,9 @@ void DebugReader::handleBreakpoint(const QByteArray &breakpointRecord) //because QJsonDocument only handle utf8-encoded json strings QString temp = QString::fromLocal8Bit(breakpointRecord); QByteArray record = temp.toUtf8(); + GDBMIResultParser parser; + GDBMIR + parser.parse(breakpointRecord,) QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(record,&error); if (error.error!=QJsonParseError::NoError) { diff --git a/RedPandaIDE/debugger.h b/RedPandaIDE/debugger.h index 0b0a122b..50259460 100644 --- a/RedPandaIDE/debugger.h +++ b/RedPandaIDE/debugger.h @@ -13,6 +13,8 @@ #include #include #include +#include "gdbmiresultparser.h" + enum class DebugCommandSource { Console, Other @@ -188,6 +190,8 @@ public: PBreakpoint breakpointAt(int line, const Editor* editor, int &index); void setBreakPointCondition(int index, const QString& condition); void sendAllBreakpointsToDebugger(); + void validateBreakpoint(int line, const QString& filename, int number); + void invalidateAllBreakpoints(); //watch vars void addWatchVar(const QString& namein); @@ -310,7 +314,7 @@ private: void runNextCmd(); QStringList tokenize(const QString& s); - void handleBreakpoint(const QByteArray& breakpointRecord); + void handleBreakpoint(const GDBMIResultParser::ParseObject& breakpoint); void processConsoleOutput(const QByteArray& line); void processResult(const QByteArray& result); void processExecAsyncRecord(const QByteArray& line); @@ -357,6 +361,7 @@ private: bool doupdatememoryview; bool doupdatelocal; + // bool mInferiorPaused; bool mProcessExited; QStringList mConsoleOutput; From aa17415b154351c1d7ded232ca58e607355a6f2f Mon Sep 17 00:00:00 2001 From: "royqh1979@gmail.com" Date: Sun, 21 Nov 2021 08:38:03 +0800 Subject: [PATCH 09/32] work save --- RedPandaIDE/debugger.cpp | 44 +++++++++++++++++++------------ RedPandaIDE/debugger.h | 4 +++ RedPandaIDE/gdbmiresultparser.cpp | 20 +++++++++++--- RedPandaIDE/gdbmiresultparser.h | 8 +++--- 4 files changed, 52 insertions(+), 24 deletions(-) diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index a873db04..3c006403 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -63,6 +63,8 @@ bool Debugger::start() connect(this, &Debugger::localsReady,pMainWindow,&MainWindow::onLocalsReady); connect(mReader, &DebugReader::cmdStarted,pMainWindow, &MainWindow::disableDebugActions); connect(mReader, &DebugReader::cmdFinished,pMainWindow, &MainWindow::enableDebugActions); + connect(mReader, &DebugReader::breakpointInfoGetted, mBreakpointModel, + &BreakpointModel::updateBreakpointNumber); mReader->start(); mReader->waitStart(); @@ -1713,24 +1715,13 @@ QStringList DebugReader::tokenize(const QString &s) return result; } -void DebugReader::handleBreakpoint(const QByteArray &breakpointRecord) +void DebugReader::handleBreakpoint(const GDBMIResultParser::ParseObject& breakpoint) { - //we have to convert record from local encoding to utf8 - //because QJsonDocument only handle utf8-encoded json strings - QString temp = QString::fromLocal8Bit(breakpointRecord); - QByteArray record = temp.toUtf8(); - GDBMIResultParser parser; - GDBMIR - parser.parse(breakpointRecord,) - QJsonParseError error; - QJsonDocument doc = QJsonDocument::fromJson(record,&error); - if (error.error!=QJsonParseError::NoError) { - mConsoleOutput.append(QString("Error when parsing breakpoint record \"%1\":").arg(temp)); - mConsoleOutput.append(error.errorString()); - return; - } - QJsonObject obj = doc.object(); - + // gdb use system encoding for file path + QString filename = QString::fromLocal8Bit(breakpoint["filename"].value()); + int line = breakpoint["line"].intValue(); + int number = breakpoint["number"].intValue(); + emit breakpointInfoGetted(filename, line , number); } QByteArray DebugReader::removeToken(const QByteArray &line) @@ -1966,6 +1957,14 @@ void BreakpointModel::removeBreakpoint(int row) endRemoveRows(); } +void BreakpointModel::invalidateAllBreakpointNumbers() +{ + foreach (PBreakpoint bp,mList) { + bp->number = -1; + } + //emit dateChanged(createIndex(0,0),) +} + PBreakpoint BreakpointModel::setBreakPointCondition(int index, const QString &condition) { PBreakpoint breakpoint = mList[index]; @@ -2045,6 +2044,17 @@ void BreakpointModel::load(const QString &filename) } } +void BreakpointModel::updateBreakpointNumber(const QString &filename, int line, int number) +{ + QFileInfo file(filename); + QString fn = file.absoluteFilePath(); + foreach (PBreakpoint bp, mList) { + if (bp->filename == fn && bp->line == line) { + bp->number = number; + } + } +} + void BreakpointModel::onFileDeleteLines(const QString &filename, int startLine, int count) { for (int i = mList.count()-1;i>=0;i--){ diff --git a/RedPandaIDE/debugger.h b/RedPandaIDE/debugger.h index 50259460..3619102a 100644 --- a/RedPandaIDE/debugger.h +++ b/RedPandaIDE/debugger.h @@ -100,6 +100,8 @@ public: void save(const QString& filename); void load(const QString& filename); public slots: + void updateBreakpointNumber(const QString& filename, int line, int number); + void invalidateAllBreakpointNumbers(); // call this when gdb is stopped void onFileDeleteLines(const QString& filename, int startLine, int count); void onFileInsertLines(const QString& filename, int startLine, int count); private: @@ -291,6 +293,8 @@ signals: void changeDebugConsoleLastLine(const QString& text); void cmdStarted(); void cmdFinished(); + + void breakpointInfoGetted(const QString& filename, int line, int number); private: void clearCmdQueue(); bool outputTerminated(QByteArray& text); diff --git a/RedPandaIDE/gdbmiresultparser.cpp b/RedPandaIDE/gdbmiresultparser.cpp index 218cc955..44b719d8 100644 --- a/RedPandaIDE/gdbmiresultparser.cpp +++ b/RedPandaIDE/gdbmiresultparser.cpp @@ -194,21 +194,35 @@ void GDBMIResultParser::skipSpaces(const char *&p) p++; } -const QString &GDBMIResultParser::ParseValue::value() const +const QByteArray &GDBMIResultParser::ParseValue::value() const { + Q_ASSERT(mType == ParseValueType::Value); return mValue; } const QList<::GDBMIResultParser::ParseObject> &GDBMIResultParser::ParseValue::array() const { + Q_ASSERT(mType == ParseValueType::Array); return mArray; } const GDBMIResultParser::ParseObject &GDBMIResultParser::ParseValue::object() const { + Q_ASSERT(mType == ParseValueType::Object); return mObject; } +int GDBMIResultParser::ParseValue::intValue(int defaultValue) const +{ + Q_ASSERT(mType == ParseValueType::Value); + bool ok; + int value = QString(mValue).toInt(&ok); + if (ok) + return value; + else + return defaultValue; +} + GDBMIResultParser::ParseValueType GDBMIResultParser::ParseValue::type() const { return mType; @@ -219,7 +233,7 @@ GDBMIResultParser::ParseValue::ParseValue(): } -GDBMIResultParser::ParseValue::ParseValue(const QString &value): +GDBMIResultParser::ParseValue::ParseValue(const QByteArray &value): mValue(value), mType(ParseValueType::Value) { @@ -237,7 +251,7 @@ GDBMIResultParser::ParseValue::ParseValue(const QList &array): { } -GDBMIResultParser::ParseValue &GDBMIResultParser::ParseValue::operator=(const QString &value) +GDBMIResultParser::ParseValue &GDBMIResultParser::ParseValue::operator=(const QByteArray &value) { Q_ASSERT(mType == ParseValueType::NotAssigned); mType = ParseValueType::Value; diff --git a/RedPandaIDE/gdbmiresultparser.h b/RedPandaIDE/gdbmiresultparser.h index b989d91e..f16781aa 100644 --- a/RedPandaIDE/gdbmiresultparser.h +++ b/RedPandaIDE/gdbmiresultparser.h @@ -46,20 +46,20 @@ public: class ParseValue { public: explicit ParseValue(); - explicit ParseValue(const QString& value); + explicit ParseValue(const QByteArray& value); explicit ParseValue(const ParseObject &object); explicit ParseValue(const QList& array); ParseValue(const ParseValue&) = delete; - const QString &value() const; + const QByteArray &value() const; const QList &array() const; const ParseObject &object() const; ParseValueType type() const; - ParseValue& operator=(const QString& value); + ParseValue& operator=(const QByteArray& value); ParseValue& operator=(const ParseObject& object); ParseValue& operator=(const QList& array); ParseValue& operator=(const ParseValue& value); private: - QString mValue; + QByteArray mValue; QList mArray; ParseObject mObject; ParseValueType mType; From a927c2cc0e80e7192969d0cbf718cfa0debb35a0 Mon Sep 17 00:00:00 2001 From: "royqh1979@gmail.com" Date: Sun, 21 Nov 2021 10:36:50 +0800 Subject: [PATCH 10/32] work save --- RedPandaIDE/debugger.cpp | 39 +++++++++++++++++-------------- RedPandaIDE/gdbmiresultparser.cpp | 36 ++++++++++++++++++++++++++++ RedPandaIDE/gdbmiresultparser.h | 3 +++ 3 files changed, 61 insertions(+), 17 deletions(-) diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index 3c006403..a3fb8282 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -1203,28 +1203,35 @@ void DebugReader::processResult(const QByteArray &result) } } -void DebugReader::processExecAsyncRecord(const QString &line) +void DebugReader::processExecAsyncRecord(const QByteArray &line) { - if (line.startsWith("*running")) { + QByteArray result; + GDBMIResultParser::ParseObject multiValues; + GDBMIResultParser parser; + if (!parser.parseAsyncResult(line,result,multiValues)) + return; + if (result == "running") { mInferiorPaused = false; return; } - if (line.startsWith("*stopped")) { + if (result == "*stopped") { mInferiorPaused = true; - QStringList props = line.split(','); - if (props.count()<2) - return; - QString reason = props[1]; - QRegExp exp("^reason=\"(.+)\"$"); - reason = exp.cap(1); - if (reason.isEmpty()) - return; - if (reason.startsWith("exited")) { + QByteArray reason = multiValues["reason"].value(); + if (reason == "exited") { //inferior exited, gdb should terminate too mProcessExited = true; return; } - if (reason==("signal-received")) { + if (reason == "exited-normally") { + //inferior exited, gdb should terminate too + mProcessExited = true; + return; + } + if (reason == "signal-received") { + //todo: signal received + return; + } + if (reason == "breakpoint-hit") { //todo: signal received return; } @@ -1718,7 +1725,7 @@ QStringList DebugReader::tokenize(const QString &s) void DebugReader::handleBreakpoint(const GDBMIResultParser::ParseObject& breakpoint) { // gdb use system encoding for file path - QString filename = QString::fromLocal8Bit(breakpoint["filename"].value()); + QString filename = QFileInfo(QString::fromLocal8Bit(breakpoint["filename"].value())).absoluteFilePath(); int line = breakpoint["line"].intValue(); int number = breakpoint["number"].intValue(); emit breakpointInfoGetted(filename, line , number); @@ -2046,10 +2053,8 @@ void BreakpointModel::load(const QString &filename) void BreakpointModel::updateBreakpointNumber(const QString &filename, int line, int number) { - QFileInfo file(filename); - QString fn = file.absoluteFilePath(); foreach (PBreakpoint bp, mList) { - if (bp->filename == fn && bp->line == line) { + if (bp->filename == filename && bp->line == line) { bp->number = number; } } diff --git a/RedPandaIDE/gdbmiresultparser.cpp b/RedPandaIDE/gdbmiresultparser.cpp index 44b719d8..4a0620c4 100644 --- a/RedPandaIDE/gdbmiresultparser.cpp +++ b/RedPandaIDE/gdbmiresultparser.cpp @@ -31,6 +31,42 @@ bool GDBMIResultParser::parse(const QByteArray &record, GDBMIResultType &type, P return true; } +bool GDBMIResultParser::parseAsyncResult(const QByteArray &record, QByteArray &result, ParseObject &multiValue) +{ + const char* p =record.data(); + if (*p!='*') + return false; + p++; + const char* start; + while (*p && *p!=',') + p++; + result = QByteArray(start,p-start); + if (*p==0) + return true; + return parseMultiValues(p,multiValue); +} + +bool GDBMIResultParser::parseMultiValues(const char* p, ParseObject &multiValue) +{ + while (*p) { + QByteArray propName; + ParseValue propValue; + bool result = parseNameAndValue(p,propName,propValue); + if (result) { + multiValue[propName]=propValue; + } else { + return false; + } + skipSpaces(p); + if (*p!=',') + return false; + p++; //skip ',' + skipSpaces(p); + p++; + } + return true; +} + bool GDBMIResultParser::parseNameAndValue(const char *&p, QByteArray &name, ParseValue &value) { skipSpaces(p); diff --git a/RedPandaIDE/gdbmiresultparser.h b/RedPandaIDE/gdbmiresultparser.h index f16781aa..4ae71eb4 100644 --- a/RedPandaIDE/gdbmiresultparser.h +++ b/RedPandaIDE/gdbmiresultparser.h @@ -53,6 +53,7 @@ public: const QByteArray &value() const; const QList &array() const; const ParseObject &object() const; + int intValue(int defaultValue=-1) const; ParseValueType type() const; ParseValue& operator=(const QByteArray& value); ParseValue& operator=(const ParseObject& object); @@ -70,7 +71,9 @@ public: public: GDBMIResultParser(); bool parse(const QByteArray& record, GDBMIResultType& type, ParseValue& value); + bool parseAsyncResult(const QByteArray& record, QByteArray& result, ParseObject& multiValue); private: + bool parseMultiValues(const char*p, ParseObject& multiValue); bool parseNameAndValue(const char *&p,QByteArray& name, ParseValue& value); bool parseValue(const char* &p, ParseValue& value); bool parseStringValue(const char*&p, QByteArray& stringValue); From 9fd06a983797d854052afc6c194b6b074858b204 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Tue, 23 Nov 2021 21:08:33 +0800 Subject: [PATCH 11/32] work save --- RedPandaIDE/debugger.cpp | 264 ++++++++++++++++++------------ RedPandaIDE/debugger.h | 53 +++++- RedPandaIDE/gdbmiresultparser.cpp | 21 ++- RedPandaIDE/gdbmiresultparser.h | 11 +- 4 files changed, 221 insertions(+), 128 deletions(-) diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index a3fb8282..761358d5 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -12,6 +12,9 @@ #include #include #include +#include +#include +#include Debugger::Debugger(QObject *parent) : QObject(parent) { @@ -63,6 +66,7 @@ bool Debugger::start() connect(this, &Debugger::localsReady,pMainWindow,&MainWindow::onLocalsReady); connect(mReader, &DebugReader::cmdStarted,pMainWindow, &MainWindow::disableDebugActions); connect(mReader, &DebugReader::cmdFinished,pMainWindow, &MainWindow::enableDebugActions); + connect(mReader, &DebugReader::breakpointInfoGetted, mBreakpointModel, &BreakpointModel::updateBreakpointNumber); @@ -455,23 +459,17 @@ void Debugger::syncFinishedParsing() } // An evaluation variable has been processed. Forward the results - if (mReader->doevalready) { + if (mReader->evalReady()) { //pMainWindow->updateDebugEval(mReader->mEvalValue); - emit evalValueReady(mReader->mEvalValue); - mReader->mEvalValue=""; - mReader->doevalready = false; + emit evalValueReady(mReader->evalValue()); } - if (mReader->doupdatememoryview) { - emit memoryExamineReady(mReader->mMemoryValue); - mReader->mMemoryValue.clear(); - mReader->doupdatememoryview=false; + if (mReader->updateMemory()) { + emit memoryExamineReady(mReader->memoryValue()); } - if (mReader->doupdatelocal) { - emit localsReady(mReader->mLocalsValue); - mReader->mLocalsValue.clear(); - mReader->doupdatelocal=false; + if (mReader->updateLocals()) { + emit localsReady(mReader->localsValue()); } // show command output @@ -521,16 +519,17 @@ void Debugger::syncFinishedParsing() } } - if (mReader->doupdateexecution) { - if (mReader->mCurrentCmd && mReader->mCurrentCmd->source == DebugCommandSource::Console) { - pMainWindow->setActiveBreakpoint(mReader->mBreakPointFile, mReader->mBreakPointLine,false); + if (mReader->updateExecution()) { + if (mReader->currentCmd() && mReader->currentCmd()->source == DebugCommandSource::Console) { + pMainWindow->setActiveBreakpoint(mReader->breakPointFile(), mReader->breakPointLine(),false); } else { - pMainWindow->setActiveBreakpoint(mReader->mBreakPointFile, mReader->mBreakPointLine); + pMainWindow->setActiveBreakpoint(mReader->breakPointFile(), mReader->breakPointLine()); } refreshWatchVars(); // update variable information } - if (mReader->doreceivedsignal) { + if (mReader->signalReceived()) { + //SignalDialog := CreateMessageDialog(fSignal, mtError, [mbOk]); //SignalCheck := TCheckBox.Create(SignalDialog); @@ -563,7 +562,7 @@ void Debugger::syncFinishedParsing() // CPU form updates itself when spawned, don't update twice! - if ((mReader->doupdatecpuwindow && !spawnedcpuform) && (pMainWindow->cpuDialog()!=nullptr)) { + if ((mReader->updateCPUInfo() && !spawnedcpuform) && (pMainWindow->cpuDialog()!=nullptr)) { pMainWindow->cpuDialog()->updateInfo(); } } @@ -903,86 +902,6 @@ void DebugReader::handleExit() doprocessexited=true; } -void DebugReader::handleFrames() -{ - QString s = getNextLine(); - - // Is this a backtrace dump? - if (s.startsWith("#")) { - if (s.startsWith("#0")) { - mDebugger->backtraceModel()->clear(); - } - // Find function name - if (!findAnnotation(AnnotationType::TFrameFunctionName)) - return; - - PTrace trace = std::make_shared(); - trace->funcname = getNextLine(); - - // Find argument list start - if (!findAnnotation(AnnotationType::TFrameArgs)) - return; - - // Arguments are either () or detailed list - s = getNextLine(); - - while (peekNextAnnotation() == AnnotationType::TArgBegin) { - - // argument name - if (!findAnnotation(AnnotationType::TArgBegin)) - return; - - s = s + getNextLine(); - - // = - if (!findAnnotation(AnnotationType::TArgNameEnd)) - return; - s = s + ' ' + getNextLine() + ' '; // should be = - - // argument value - if (!findAnnotation(AnnotationType::TArgValue)) - return; - - s = s + getNextLine(); - - // argument end - if (!findAnnotation(AnnotationType::TArgEnd)) - return; - - s = s + getNextLine(); - } - - trace->funcname = trace->funcname + s.trimmed(); - - // source info - if (peekNextAnnotation() == AnnotationType::TFrameSourceBegin) { - // Find filename - if (!findAnnotation(AnnotationType::TFrameSourceFile)) - return; - trace->filename = getNextLine(); - // find line - if (!findAnnotation(AnnotationType::TFrameSourceLine)) - return; - trace->line = getNextLine().trimmed().toInt(); - } else { - trace->filename = ""; - trace->line = 0; - } - mDebugger->backtraceModel()->addTrace(trace); - - // Skip over the remaining frame part... - if (!findAnnotation(AnnotationType::TFrameEnd)) - return; - - // Not another one coming? Done! - if (peekNextAnnotation() != AnnotationType::TFrameBegin) { - // End of stack trace dump! - dobacktraceready = true; - } - } else - doupdatecpuwindow = true; -} - void DebugReader::handleLocalOutput() { // name(spaces)hexvalue(tab)decimalvalue @@ -1167,9 +1086,22 @@ void DebugReader::processResult(const QByteArray &result) if (!parseOk) return; switch(resultType) { + case GDBMIResultType::BreakpointTable: + case GDBMIResultType::Frame: + case GDBMIResultType::Locals: + break; case GDBMIResultType::Breakpoint: handleBreakpoint(parseValue.object()); return; + case GDBMIResultType::FrameStack: + handleStack(parseValue.array()); + return; + case GDBMIResultType::LocalVariables: + handleLocalVariables(parseValue.array()); + return; + case GDBMIResultType::Evaluation: + handleEvaluation(parseValue.value()); + return; } QByteArray name = result.mid(0,pos); @@ -1227,13 +1159,12 @@ void DebugReader::processExecAsyncRecord(const QByteArray &line) mProcessExited = true; return; } + mUpdateExecution = true; + mUpdateCPUInfo = true; + mBreakPointFile = multiValues["fullname"].pathValue(); + mBreakPointLine = multiValues["line"].intValue(); if (reason == "signal-received") { - //todo: signal received - return; - } - if (reason == "breakpoint-hit") { - //todo: signal received - return; + mSignalReceived = true; } } } @@ -1282,10 +1213,16 @@ void DebugReader::processDebugOutput(const QByteArray& debugOutput) emit parseStarted(); mConsoleOutput.clear(); + mLocalsValue.clear(); + mEvalValue.clear(); + mMemoryValue.clear(); - //try + mUpdateExecution = false; + mSignalReceived = false; + mUpdateCPUInfo = false; + mUpdateLocals = false; + mEvalReady = false; - dobacktraceready = false; dodisassemblerready = false; doregistersready = false; doevalready = false; @@ -1725,12 +1662,58 @@ QStringList DebugReader::tokenize(const QString &s) void DebugReader::handleBreakpoint(const GDBMIResultParser::ParseObject& breakpoint) { // gdb use system encoding for file path - QString filename = QFileInfo(QString::fromLocal8Bit(breakpoint["filename"].value())).absoluteFilePath(); + QString filename = breakpoint["fullname"].value(); int line = breakpoint["line"].intValue(); int number = breakpoint["number"].intValue(); emit breakpointInfoGetted(filename, line , number); } +void DebugReader::handleStack(const QList & stack) +{ + mDebugger->backtraceModel()->clear(); + foreach (const GDBMIResultParser::ParseValue& frameValue, stack) { + GDBMIResultParser::ParseObject frameObject = frameValue.object(); + PTrace trace = std::make_shared(); + trace->funcname = frameObject["func"].value(); + trace->filename = frameObject["fullname"].pathValue(); + trace->line = frameObject["fullname"].intValue(); + trace->level = frameObject["level"].intValue(0); + trace->address = frameObject["addr"].value(); + mDebugger->backtraceModel()->addTrace(trace); + } +} + +void DebugReader::handleLocalVariables(const QList &variables) +{ + mUpdateLocals=true; + foreach (const GDBMIResultParser::ParseValue& varValue, variables) { + GDBMIResultParser::ParseObject varObject = varValue.object(); + mLocalsValue.append(QString("%1 = %2") + .arg(varObject["name"].value(),varObject["value"].value())); + } +} + +void DebugReader::handleEvaluation(const QString &value) +{ + mEvalReady = true; + mEvalValue = value; +} + +void DebugReader::handleMemory(const QList &rows) +{ + mUpdateMemory = true; + foreach (const GDBMIResultParser::ParseValue& row, rows) { + GDBMIResultParser::ParseObject rowObject = row.object(); + QList data = rowObject["data"].array(); + QStringList values; + foreach (const GDBMIResultParser::ParseValue& val, data) { + values.append(val.value()); + } + mLocalsValue.append(QString("%1 %2") + .arg(rowObject["addr"].value(),values.join(" "))); + } +} + QByteArray DebugReader::removeToken(const QByteArray &line) { int p=0; @@ -1746,6 +1729,71 @@ QByteArray DebugReader::removeToken(const QByteArray &line) return line; } +const QStringList &DebugReader::memoryValue() const +{ + return mMemoryValue; +} + +bool DebugReader::updateMemory() const +{ + return mUpdateMemory; +} + +const QString &DebugReader::evalValue() const +{ + return mEvalValue; +} + +bool DebugReader::evalReady() const +{ + return mEvalReady; +} + +const QStringList &DebugReader::localsValue() const +{ + return mLocalsValue; +} + +bool DebugReader::updateLocals() const +{ + return mUpdateLocals; +} + +bool DebugReader::updateCPUInfo() const +{ + return mUpdateCPUInfo; +} + +const PDebugCommand &DebugReader::currentCmd() const +{ + return mCurrentCmd; +} + +const QString &DebugReader::breakPointFile() const +{ + return mBreakPointFile; +} + +int DebugReader::breakPointLine() const +{ + return mBreakPointLine; +} + +const QStringList &DebugReader::consoleOutput() const +{ + return mConsoleOutput; +} + +bool DebugReader::signalReceived() const +{ + return mSignalReceived; +} + +bool DebugReader::updateExecution() const +{ + return mUpdateExecution; +} + bool DebugReader::processExited() const { return mProcessExited; @@ -1791,7 +1839,6 @@ bool DebugReader::waitStart() mStartSemaphore.acquire(1); } - void DebugReader::run() { mStop = false; @@ -2056,6 +2103,7 @@ void BreakpointModel::updateBreakpointNumber(const QString &filename, int line, foreach (PBreakpoint bp, mList) { if (bp->filename == filename && bp->line == line) { bp->number = number; + return; } } } diff --git a/RedPandaIDE/debugger.h b/RedPandaIDE/debugger.h index 3619102a..c92ab62a 100644 --- a/RedPandaIDE/debugger.h +++ b/RedPandaIDE/debugger.h @@ -55,7 +55,9 @@ using PBreakpoint = std::shared_ptr; struct Trace { QString funcname; QString filename; + QString address; int line; + int level; }; using PTrace = std::shared_ptr; @@ -281,6 +283,31 @@ public: bool processExited() const; + bool updateExecution() const; + + bool signalReceived() const; + + const QStringList &consoleOutput() const; + + int breakPointLine() const; + + const QString &breakPointFile() const; + + const PDebugCommand ¤tCmd() const; + + bool updateCPUInfo() const; + + bool updateLocals() const; + + const QStringList &localsValue() const; + + bool evalReady() const; + + const QString &evalValue() const; + + bool updateMemory() const; + + const QStringList &memoryValue() const; signals: void parseStarted(); @@ -302,7 +329,6 @@ private: void handleDisplay(); void handleError(); void handleExit(); - void handleFrames(); void handleLocalOutput(); void handleLocals(); void handleMemory(); @@ -319,6 +345,10 @@ private: QStringList tokenize(const QString& s); void handleBreakpoint(const GDBMIResultParser::ParseObject& breakpoint); + void handleStack(const QList & stack); + void handleLocalVariables(const QList & variables); + void handleEvaluation(const QString& value); + void handleMemory(const QList & rows); void processConsoleOutput(const QByteArray& line); void processResult(const QByteArray& result); void processExecAsyncRecord(const QByteArray& line); @@ -345,16 +375,11 @@ private: //fWatchView: TTreeView; int mIndex; - int mBreakPointLine; - QString mBreakPointFile; - QString mEvalValue; - QStringList mMemoryValue; - QStringList mLocalsValue; + QString mSignal; bool mUseUTF8; // attempt to cut down on Synchronize calls - bool dobacktraceready; bool dodisassemblerready; bool doregistersready; bool doevalready; @@ -363,12 +388,24 @@ private: bool doreceivedsignal; bool doreceivedsfwarning; bool doupdatememoryview; - bool doupdatelocal; // bool mInferiorPaused; bool mProcessExited; + + bool mUpdateExecution; + bool mSignalReceived; + bool mUpdateCPUInfo; + bool mUpdateLocals; + bool mEvalReady; + bool mUpdateMemory; + QStringList mConsoleOutput; + int mBreakPointLine; + QString mBreakPointFile; + QStringList mLocalsValue; + QString mEvalValue; + QStringList mMemoryValue; bool mStop; // QThread interface diff --git a/RedPandaIDE/gdbmiresultparser.cpp b/RedPandaIDE/gdbmiresultparser.cpp index 4a0620c4..cba4e8a3 100644 --- a/RedPandaIDE/gdbmiresultparser.cpp +++ b/RedPandaIDE/gdbmiresultparser.cpp @@ -1,5 +1,6 @@ #include "gdbmiresultparser.h" +#include #include GDBMIResultParser::GDBMIResultParser() @@ -172,7 +173,7 @@ bool GDBMIResultParser::parseObject(const char *&p, ParseObject &obj) return false; } -bool GDBMIResultParser::parseArray(const char *&p, QList &array) +bool GDBMIResultParser::parseArray(const char *&p, QList &array) { if (*p!='[') return false; @@ -180,10 +181,10 @@ bool GDBMIResultParser::parseArray(const char *&p, QList &GDBMIResultParser::ParseValue::array() const +const QList<::GDBMIResultParser::ParseValue> &GDBMIResultParser::ParseValue::array() const { Q_ASSERT(mType == ParseValueType::Array); return mArray; @@ -259,6 +260,12 @@ int GDBMIResultParser::ParseValue::intValue(int defaultValue) const return defaultValue; } +QString GDBMIResultParser::ParseValue::pathValue() const +{ + Q_ASSERT(mType == ParseValueType::Value); + return QFileInfo(QString::fromLocal8Bit(mValue)).absoluteFilePath(); +} + GDBMIResultParser::ParseValueType GDBMIResultParser::ParseValue::type() const { return mType; @@ -281,7 +288,7 @@ GDBMIResultParser::ParseValue::ParseValue(const ParseObject &object): { } -GDBMIResultParser::ParseValue::ParseValue(const QList &array): +GDBMIResultParser::ParseValue::ParseValue(const QList &array): mArray(array), mType(ParseValueType::Array) { @@ -301,7 +308,7 @@ GDBMIResultParser::ParseValue &GDBMIResultParser::ParseValue::operator=(const Pa mObject = object; } -GDBMIResultParser::ParseValue &GDBMIResultParser::ParseValue::operator=(const QList& array) +GDBMIResultParser::ParseValue &GDBMIResultParser::ParseValue::operator=(const QList& array) { Q_ASSERT(mType == ParseValueType::NotAssigned); mType = ParseValueType::Array; diff --git a/RedPandaIDE/gdbmiresultparser.h b/RedPandaIDE/gdbmiresultparser.h index 4ae71eb4..a895c73f 100644 --- a/RedPandaIDE/gdbmiresultparser.h +++ b/RedPandaIDE/gdbmiresultparser.h @@ -48,20 +48,21 @@ public: explicit ParseValue(); explicit ParseValue(const QByteArray& value); explicit ParseValue(const ParseObject &object); - explicit ParseValue(const QList& array); + explicit ParseValue(const QList& array); ParseValue(const ParseValue&) = delete; const QByteArray &value() const; - const QList &array() const; + const QList &array() const; const ParseObject &object() const; int intValue(int defaultValue=-1) const; + QString pathValue() const; ParseValueType type() const; ParseValue& operator=(const QByteArray& value); ParseValue& operator=(const ParseObject& object); - ParseValue& operator=(const QList& array); + ParseValue& operator=(const QList& array); ParseValue& operator=(const ParseValue& value); private: QByteArray mValue; - QList mArray; + QList mArray; ParseObject mObject; ParseValueType mType; }; @@ -78,7 +79,7 @@ private: bool parseValue(const char* &p, ParseValue& value); bool parseStringValue(const char*&p, QByteArray& stringValue); bool parseObject(const char*&p, ParseObject& obj); - bool parseArray(const char*&p, QList& array); + bool parseArray(const char*&p, QList& array); void skipSpaces(const char* &p); bool isNameChar(char ch); bool isSpaceChar(char ch); From fdfa7c779f9eaf540f652f189967957ced796f6c Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Wed, 24 Nov 2021 10:07:35 +0800 Subject: [PATCH 12/32] work save --- RedPandaIDE/codesnippetsmanager.h | 2 - RedPandaIDE/cpprefacter.h | 1 - RedPandaIDE/debugger.cpp | 122 ++++++-------------- RedPandaIDE/debugger.h | 18 +-- RedPandaIDE/editor.cpp | 2 +- RedPandaIDE/iconsmanager.h | 1 - RedPandaIDE/mainwindow.cpp | 24 ++-- RedPandaIDE/parser/cpppreprocessor.h | 3 - RedPandaIDE/parser/cpptokenizer.h | 1 - RedPandaIDE/parser/statementmodel.h | 2 - RedPandaIDE/projecttemplate.h | 2 - RedPandaIDE/shortcutmanager.h | 2 - RedPandaIDE/symbolusagemanager.h | 1 - RedPandaIDE/thememanager.h | 1 - RedPandaIDE/todoparser.h | 1 - RedPandaIDE/toolsmanager.h | 2 - RedPandaIDE/widgets/functiontooltipwidget.h | 1 - 17 files changed, 57 insertions(+), 129 deletions(-) diff --git a/RedPandaIDE/codesnippetsmanager.h b/RedPandaIDE/codesnippetsmanager.h index bad5222a..a66c7914 100644 --- a/RedPandaIDE/codesnippetsmanager.h +++ b/RedPandaIDE/codesnippetsmanager.h @@ -49,8 +49,6 @@ public: const QString &newFileTemplate() const; void setNewFileTemplate(const QString &newNewFileTemplate); -signals: - private: void loadSnippets(); void saveSnippets(); diff --git a/RedPandaIDE/cpprefacter.h b/RedPandaIDE/cpprefacter.h index ca9cab6f..e4caaa6d 100644 --- a/RedPandaIDE/cpprefacter.h +++ b/RedPandaIDE/cpprefacter.h @@ -19,7 +19,6 @@ public: bool findOccurence(const QString& statementFullname, SearchFileScope scope); void renameSymbol(Editor* editor, const BufferCoord& pos, const QString& word, const QString& newWord); -signals: private: void doFindOccurenceInEditor(PStatement statement, Editor* editor, const PCppParser& parser); void doFindOccurenceInProject(PStatement statement, std::shared_ptr project, const PCppParser& parser); diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index 761358d5..bad90672 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -63,12 +63,16 @@ bool Debugger::start() connect(mReader, &QThread::finished,this,&Debugger::clearUpReader); connect(mReader, &DebugReader::parseFinished,this,&Debugger::syncFinishedParsing,Qt::BlockingQueuedConnection); connect(mReader, &DebugReader::changeDebugConsoleLastLine,this,&Debugger::onChangeDebugConsoleLastline); - connect(this, &Debugger::localsReady,pMainWindow,&MainWindow::onLocalsReady); connect(mReader, &DebugReader::cmdStarted,pMainWindow, &MainWindow::disableDebugActions); connect(mReader, &DebugReader::cmdFinished,pMainWindow, &MainWindow::enableDebugActions); connect(mReader, &DebugReader::breakpointInfoGetted, mBreakpointModel, &BreakpointModel::updateBreakpointNumber); + connect(mReader, &DebugReader::localsUpdated, pMainWindow, + &MainWindow::onLocalsReady); + connect(mReader, &DebugReader::memoryUpdated,[this](const QStringList memory) { + emit memoryExamineReady(memory); + }); mReader->start(); mReader->waitStart(); @@ -439,7 +443,7 @@ void Debugger::syncFinishedParsing() bool spawnedcpuform = false; // GDB determined that the source code is more recent than the executable. Ask the user if he wants to rebuild. - if (mReader->doreceivedsfwarning) { + if (mReader->receivedSFWarning()) { if (QMessageBox::question(pMainWindow, tr("Compile"), tr("Source file is more recent than executable.")+"

" + tr("Recompile?"), @@ -458,20 +462,6 @@ void Debugger::syncFinishedParsing() return; } - // An evaluation variable has been processed. Forward the results - if (mReader->evalReady()) { - //pMainWindow->updateDebugEval(mReader->mEvalValue); - emit evalValueReady(mReader->evalValue()); - } - - if (mReader->updateMemory()) { - emit memoryExamineReady(mReader->memoryValue()); - } - - if (mReader->updateLocals()) { - emit localsReady(mReader->localsValue()); - } - // show command output if (pSettings->debugger().showCommandLog() || (mReader->mCurrentCmd && mReader->mCurrentCmd->showInConsole)) { @@ -567,7 +557,7 @@ void Debugger::syncFinishedParsing() } } -void Debugger::onChangeDebugConsoleLastline(const QString &text) +void Debugger::onChangeDebugConsoleLastline(const QString& text) { //pMainWindow->changeDebugOutputLastline(text); pMainWindow->addDebugOutput(text); @@ -1143,11 +1133,12 @@ void DebugReader::processExecAsyncRecord(const QByteArray &line) if (!parser.parseAsyncResult(line,result,multiValues)) return; if (result == "running") { - mInferiorPaused = false; + mInferiorRunning = true; + emit inferiorContinued(); return; } if (result == "*stopped") { - mInferiorPaused = true; + mInferiorRunning = false; QByteArray reason = multiValues["reason"].value(); if (reason == "exited") { //inferior exited, gdb should terminate too @@ -1159,10 +1150,14 @@ void DebugReader::processExecAsyncRecord(const QByteArray &line) mProcessExited = true; return; } - mUpdateExecution = true; + if (reason == "exited-signalled") { + //inferior exited, gdb should terminate too + mProcessExited = true; + mSignalReceived = true; + return; + } mUpdateCPUInfo = true; - mBreakPointFile = multiValues["fullname"].pathValue(); - mBreakPointLine = multiValues["line"].intValue(); + emit inferiorStopped(multiValues["fullname"].pathValue(), multiValues["line"].intValue()); if (reason == "signal-received") { mSignalReceived = true; } @@ -1222,6 +1217,7 @@ void DebugReader::processDebugOutput(const QByteArray& debugOutput) mUpdateCPUInfo = false; mUpdateLocals = false; mEvalReady = false; + mReceivedSFWarning = false; dodisassemblerready = false; doregistersready = false; @@ -1260,62 +1256,6 @@ void DebugReader::processDebugOutput(const QByteArray& debugOutput) } } - - // Global checks - if (mOutput.indexOf("warning: Source file is more recent than executable.") >= 0) - doreceivedsfwarning = true; - - mIndex = 0; - AnnotationType nextAnnotation; - do { - nextAnnotation = getNextAnnotation(); - switch(nextAnnotation) { - case AnnotationType::TValueHistoryValue: - handleValueHistoryValue(); - break; - case AnnotationType::TSignal: - handleSignal(); - break; - case AnnotationType::TExit: - handleExit(); - break; - case AnnotationType::TFrameBegin: - handleFrames(); - break; - case AnnotationType::TInfoAsm: - handleDisassembly(); - break; - case AnnotationType::TInfoReg: - handleRegisters(); - break; - case AnnotationType::TLocal: - handleLocals(); - break; - case AnnotationType::TParam: - handleParams(); - break; - case AnnotationType::TMemory: - handleMemory(); - break; - case AnnotationType::TErrorBegin: - handleError(); - break; - case AnnotationType::TDisplayBegin: - handleDisplay(); - break; - case AnnotationType::TSource: - handleSource(); - break; - default: - break; - } - } while (nextAnnotation != AnnotationType::TEOF); - - // Only update once per update at most - //finally - //WatchView.Items.EndUpdate; - //end; - emit parseFinished(); } @@ -1685,23 +1625,23 @@ void DebugReader::handleStack(const QList & stack void DebugReader::handleLocalVariables(const QList &variables) { - mUpdateLocals=true; + QStringList locals; foreach (const GDBMIResultParser::ParseValue& varValue, variables) { GDBMIResultParser::ParseObject varObject = varValue.object(); - mLocalsValue.append(QString("%1 = %2") + locals.append(QString("%1 = %2") .arg(varObject["name"].value(),varObject["value"].value())); } + emit localsUpdated(locals); } void DebugReader::handleEvaluation(const QString &value) { - mEvalReady = true; - mEvalValue = value; + emit evalUpdated(value); } void DebugReader::handleMemory(const QList &rows) { - mUpdateMemory = true; + QStringList memory; foreach (const GDBMIResultParser::ParseValue& row, rows) { GDBMIResultParser::ParseObject rowObject = row.object(); QList data = rowObject["data"].array(); @@ -1709,9 +1649,10 @@ void DebugReader::handleMemory(const QList &rows) foreach (const GDBMIResultParser::ParseValue& val, data) { values.append(val.value()); } - mLocalsValue.append(QString("%1 %2") + memory.append(QString("%1 %2") .arg(rowObject["addr"].value(),values.join(" "))); } + emit memoryUpdated(memory); } QByteArray DebugReader::removeToken(const QByteArray &line) @@ -1729,6 +1670,11 @@ QByteArray DebugReader::removeToken(const QByteArray &line) return line; } +bool DebugReader::receivedSFWarning() const +{ + return mReceivedSFWarning; +} + const QStringList &DebugReader::memoryValue() const { return mMemoryValue; @@ -1842,7 +1788,7 @@ bool DebugReader::waitStart() void DebugReader::run() { mStop = false; - mInferiorPaused = false; + mInferiorRunning = false; mProcessExited = false; bool errorOccurred = false; QString cmd = mDebuggerPath; @@ -2098,7 +2044,7 @@ void BreakpointModel::load(const QString &filename) } } -void BreakpointModel::updateBreakpointNumber(const QString &filename, int line, int number) +void BreakpointModel::updateBreakpointNumber(const QString& filename, int line, int number) { foreach (PBreakpoint bp, mList) { if (bp->filename == filename && bp->line == line) { @@ -2108,7 +2054,7 @@ void BreakpointModel::updateBreakpointNumber(const QString &filename, int line, } } -void BreakpointModel::onFileDeleteLines(const QString &filename, int startLine, int count) +void BreakpointModel::onFileDeleteLines(const QString& filename, int startLine, int count) { for (int i = mList.count()-1;i>=0;i--){ PBreakpoint breakpoint = mList[i]; @@ -2124,7 +2070,7 @@ void BreakpointModel::onFileDeleteLines(const QString &filename, int startLine, } } -void BreakpointModel::onFileInsertLines(const QString &filename, int startLine, int count) +void BreakpointModel::onFileInsertLines(const QString& filename, int startLine, int count) { for (int i = mList.count()-1;i>=0;i--){ PBreakpoint breakpoint = mList[i]; diff --git a/RedPandaIDE/debugger.h b/RedPandaIDE/debugger.h index c92ab62a..a1674274 100644 --- a/RedPandaIDE/debugger.h +++ b/RedPandaIDE/debugger.h @@ -309,6 +309,8 @@ public: const QStringList &memoryValue() const; + bool receivedSFWarning() const; + signals: void parseStarted(); void invalidateAllVars(); @@ -322,6 +324,11 @@ signals: void cmdFinished(); void breakpointInfoGetted(const QString& filename, int line, int number); + void inferiorContinued(); + void inferiorStopped(const QString& filename, int line); + void localsUpdated(const QStringList& localsValue); + void evalUpdated(const QString& value); + void memoryUpdated(const QStringList& memoryValues); private: void clearCmdQueue(); bool outputTerminated(QByteArray& text); @@ -374,7 +381,6 @@ private: QProcess* mProcess; //fWatchView: TTreeView; - int mIndex; QString mSignal; bool mUseUTF8; @@ -390,22 +396,18 @@ private: bool doupdatememoryview; // - bool mInferiorPaused; + bool mInferiorRunning; bool mProcessExited; bool mUpdateExecution; bool mSignalReceived; bool mUpdateCPUInfo; - bool mUpdateLocals; - bool mEvalReady; - bool mUpdateMemory; + bool mReceivedSFWarning; QStringList mConsoleOutput; int mBreakPointLine; QString mBreakPointFile; - QStringList mLocalsValue; - QString mEvalValue; - QStringList mMemoryValue; + bool mStop; // QThread interface diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index 08cb8d76..a27d939a 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -1513,7 +1513,7 @@ void Editor::onGutterClicked(Qt::MouseButton button, int , int , int line) mGutterClickedLine = line; } -void Editor::onTipEvalValueReady(const QString &value) +void Editor::onTipEvalValueReady(const QString& value) { if (mCurrentWord == mCurrentDebugTipWord) { QString newValue; diff --git a/RedPandaIDE/iconsmanager.h b/RedPandaIDE/iconsmanager.h index e59fd4ff..5cf72a8b 100644 --- a/RedPandaIDE/iconsmanager.h +++ b/RedPandaIDE/iconsmanager.h @@ -23,7 +23,6 @@ public: const PIcon &bookmark() const; const PIcon &folder() const; -signals: private: PIcon mSyntaxError; PIcon mSyntaxWarning; diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 43933950..f24511cf 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -2895,7 +2895,7 @@ void MainWindow::onShowInsertCodeSnippetMenu() } -void MainWindow::onEditorContextMenu(const QPoint &pos) +void MainWindow::onEditorContextMenu(const QPoint& pos) { Editor * editor = mEditorList->getEditor(); if (!editor) @@ -2964,12 +2964,12 @@ void MainWindow::onEditorContextMenu(const QPoint &pos) menu.exec(editor->viewport()->mapToGlobal(pos)); } -void MainWindow::onEditorRightTabContextMenu(const QPoint &pos) +void MainWindow::onEditorRightTabContextMenu(const QPoint& pos) { onEditorTabContextMenu(ui->EditorTabsRight,pos); } -void MainWindow::onEditorLeftTabContextMenu(const QPoint &pos) +void MainWindow::onEditorLeftTabContextMenu(const QPoint& pos) { onEditorTabContextMenu(ui->EditorTabsLeft,pos); } @@ -3031,7 +3031,7 @@ void MainWindow::onTodoParseStarted(const QString&) mTodoModel.clear(); } -void MainWindow::onTodoParsing(const QString &filename, int lineNo, int ch, const QString &line) +void MainWindow::onTodoParsing(const QString& filename, int lineNo, int ch, const QString& line) { mTodoModel.addItem(filename,lineNo,ch,line); } @@ -3485,7 +3485,7 @@ void MainWindow::onCompilerSetChanged(int index) pSettings->compilerSets().saveDefaultIndex(); } -void MainWindow::onCompileLog(const QString &msg) +void MainWindow::onCompileLog(const QString& msg) { ui->txtCompilerOutput->appendPlainText(msg); ui->txtCompilerOutput->moveCursor(QTextCursor::End); @@ -3626,12 +3626,12 @@ void MainWindow::onCompileFinished(bool isCheckSyntax) updateAppTitle(); } -void MainWindow::onCompileErrorOccured(const QString &reason) +void MainWindow::onCompileErrorOccured(const QString& reason) { QMessageBox::critical(this,tr("Compile Failed"),reason); } -void MainWindow::onRunErrorOccured(const QString &reason) +void MainWindow::onRunErrorOccured(const QString& reason) { mCompilerManager->stopRun(); QMessageBox::critical(this,tr("Run Failed"),reason); @@ -3666,7 +3666,7 @@ void MainWindow::onOJProblemCaseStarted(const QString& id,int current, int total } } -void MainWindow::onOJProblemCaseFinished(const QString &id, int current, int total) +void MainWindow::onOJProblemCaseFinished(const QString& id, int current, int total) { int row = mOJProblemModel.getCaseIndexById(id); if (row>=0) { @@ -3695,7 +3695,7 @@ void MainWindow::cleanUpCPUDialog() ptr->deleteLater(); } -void MainWindow::onDebugCommandInput(const QString &command) +void MainWindow::onDebugCommandInput(const QString& command) { if (mDebugger->executing()) { mDebugger->sendCommand(command,"",true,true); @@ -4137,14 +4137,14 @@ void MainWindow::onEndParsing(int total, int) } } -void MainWindow::onEvalValueReady(const QString &value) +void MainWindow::onEvalValueReady(const QString& value) { updateDebugEval(value); disconnect(mDebugger, &Debugger::evalValueReady, this, &MainWindow::onEvalValueReady); } -void MainWindow::onMemoryExamineReady(const QStringList &value) +void MainWindow::onMemoryExamineReady(const QStringList& value) { ui->txtMemoryView->clear(); foreach (QString s, value) { @@ -4156,7 +4156,7 @@ void MainWindow::onMemoryExamineReady(const QStringList &value) this, &MainWindow::onMemoryExamineReady); } -void MainWindow::onLocalsReady(const QStringList &value) +void MainWindow::onLocalsReady(const QStringList& value) { ui->txtLocals->clear(); foreach (QString s, value) { diff --git a/RedPandaIDE/parser/cpppreprocessor.h b/RedPandaIDE/parser/cpppreprocessor.h index 1addf7ba..85ab0c49 100644 --- a/RedPandaIDE/parser/cpppreprocessor.h +++ b/RedPandaIDE/parser/cpppreprocessor.h @@ -74,9 +74,6 @@ public: const QList &includePathList() const; const QList &projectIncludePathList() const; - -signals: - private: void preprocessBuffer(); void skipToEndOfPreprocessor(); diff --git a/RedPandaIDE/parser/cpptokenizer.h b/RedPandaIDE/parser/cpptokenizer.h index 4f275984..a7c219c7 100644 --- a/RedPandaIDE/parser/cpptokenizer.h +++ b/RedPandaIDE/parser/cpptokenizer.h @@ -21,7 +21,6 @@ public: const TokenList& tokens(); PToken operator[](int i); int tokenCount(); -signals: private: void addToken(const QString& sText, int iLine); void advance(); diff --git a/RedPandaIDE/parser/statementmodel.h b/RedPandaIDE/parser/statementmodel.h index 3077b568..1608b592 100644 --- a/RedPandaIDE/parser/statementmodel.h +++ b/RedPandaIDE/parser/statementmodel.h @@ -22,8 +22,6 @@ public: #ifdef QT_DEBUG void dumpAll(const QString& logFile); #endif -signals: - private: void addMember(StatementMap& map, const PStatement& statement); int deleteMember(StatementMap& map, const PStatement& statement); diff --git a/RedPandaIDE/projecttemplate.h b/RedPandaIDE/projecttemplate.h index bc360319..314c728f 100644 --- a/RedPandaIDE/projecttemplate.h +++ b/RedPandaIDE/projecttemplate.h @@ -54,8 +54,6 @@ private: QString mIcon; // icon in project form PSimpleIni mIni; int mVersion; -signals: - }; using PProjectTemplate = std::shared_ptr; diff --git a/RedPandaIDE/shortcutmanager.h b/RedPandaIDE/shortcutmanager.h index 339aa989..cf4759bc 100644 --- a/RedPandaIDE/shortcutmanager.h +++ b/RedPandaIDE/shortcutmanager.h @@ -26,8 +26,6 @@ public: void setShortcuts(QList shortcuts); void applyTo(QList actions); void applyTo(QAction* action); -signals: -private: private: QMap mShortcuts; diff --git a/RedPandaIDE/symbolusagemanager.h b/RedPandaIDE/symbolusagemanager.h index b788d733..c5cac2ce 100644 --- a/RedPandaIDE/symbolusagemanager.h +++ b/RedPandaIDE/symbolusagemanager.h @@ -22,7 +22,6 @@ public: void reset(); PSymbolUsage findUsage(const QString& fullName) const; void updateUsage(const QString& symbol, int count); -signals: private: QHash mUsages; }; diff --git a/RedPandaIDE/thememanager.h b/RedPandaIDE/thememanager.h index 9dd425f3..23a8e65d 100644 --- a/RedPandaIDE/thememanager.h +++ b/RedPandaIDE/thememanager.h @@ -86,7 +86,6 @@ class ThemeManager : public QObject public: explicit ThemeManager(QObject *parent = nullptr); PAppTheme theme(const QString& themeName); -signals: }; #endif // THEMEMANAGER_H diff --git a/RedPandaIDE/todoparser.h b/RedPandaIDE/todoparser.h index 7cbf8c74..31e91f42 100644 --- a/RedPandaIDE/todoparser.h +++ b/RedPandaIDE/todoparser.h @@ -64,7 +64,6 @@ public: void parseFile(const QString& filename); bool parsing() const; -signals: private: TodoThread* mThread; QRecursiveMutex mMutex; diff --git a/RedPandaIDE/toolsmanager.h b/RedPandaIDE/toolsmanager.h index d14ebe64..9f6bc1e1 100644 --- a/RedPandaIDE/toolsmanager.h +++ b/RedPandaIDE/toolsmanager.h @@ -24,8 +24,6 @@ public: const QList &tools() const; PToolItem findTool(const QString& title); void setTools(const QList &newTools); - -signals: private: QList mTools; }; diff --git a/RedPandaIDE/widgets/functiontooltipwidget.h b/RedPandaIDE/widgets/functiontooltipwidget.h index d4d8f14f..aab4ab22 100644 --- a/RedPandaIDE/widgets/functiontooltipwidget.h +++ b/RedPandaIDE/widgets/functiontooltipwidget.h @@ -37,7 +37,6 @@ public: const QString &functionFullName() const; void setFunctioFullName(const QString &newFunctioFullName); -signals: private: QStringList splitArgs(QString args); private: From b17406eb07f3340f2fda524d1eadbbbaa2e91eb7 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Wed, 24 Nov 2021 17:53:25 +0800 Subject: [PATCH 13/32] work save --- RedPandaIDE/debugger.cpp | 788 +++++------------------------- RedPandaIDE/debugger.h | 45 +- RedPandaIDE/editor.cpp | 2 +- RedPandaIDE/gdbmiresultparser.cpp | 147 +++++- RedPandaIDE/gdbmiresultparser.h | 9 +- RedPandaIDE/mainwindow.cpp | 23 +- RedPandaIDE/mainwindow.h | 2 +- RedPandaIDE/qsynedit/SynEdit.cpp | 14 +- 8 files changed, 296 insertions(+), 734 deletions(-) diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index bad90672..b2df715a 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -70,9 +70,14 @@ bool Debugger::start() &BreakpointModel::updateBreakpointNumber); connect(mReader, &DebugReader::localsUpdated, pMainWindow, &MainWindow::onLocalsReady); - connect(mReader, &DebugReader::memoryUpdated,[this](const QStringList memory) { + connect(mReader, &DebugReader::memoryUpdated,[this](const QStringList& memory) { emit memoryExamineReady(memory); }); + connect(mReader, &DebugReader::evalUpdated,[this](const QString& value) { + emit evalValueReady(value); + }); + connect(mReader, &DebugReader::inferiorStopped,pMainWindow, + &MainWindow::setActiveBreakpoint); mReader->start(); mReader->waitStart(); @@ -133,10 +138,10 @@ WatchModel *Debugger::watchModel() const return mWatchModel; } -void Debugger::sendCommand(const QString &command, const QString ¶ms, bool updateWatch, bool showInConsole, DebugCommandSource source) +void Debugger::sendCommand(const QString &command, const QString ¶ms, DebugCommandSource source) { if (mExecuting && mReader) { - mReader->postCommand(command,params,updateWatch,showInConsole,source); + mReader->postCommand(command,params,source); } } @@ -463,60 +468,41 @@ void Debugger::syncFinishedParsing() } // show command output - if (pSettings->debugger().showCommandLog() || - (mReader->mCurrentCmd && mReader->mCurrentCmd->showInConsole)) { + if (pSettings->debugger().showCommandLog() ) { if (pSettings->debugger().showAnnotations()) { - QString strOutput = mReader->mOutput; - strOutput.replace(QChar(26),'>'); - pMainWindow->addDebugOutput(strOutput); - pMainWindow->addDebugOutput(""); - pMainWindow->addDebugOutput(""); - } else { - QStringList strList = textToLines(mReader->mOutput); - QStringList outStrList; - bool addToLastLine=false; - for (int i=0;i0) { - outStrList[outStrList.size()-1]+=strOutput; - } else { - outStrList.append(strOutput); - } - addToLastLine = false; - } + for (const QString& line:mReader->fullOutput()) { + pMainWindow->addDebugOutput(line); } - for (const QString& line:outStrList) { + } else { + for (const QString& line:mReader->consoleOutput()) { pMainWindow->addDebugOutput(line); } } } // Some part of the CPU form has been updated - if (pMainWindow->cpuDialog()!=nullptr && !mReader->doreceivedsignal) { - if (mReader->doregistersready) { - mRegisterModel->update(mReader->mRegisters); - mReader->mRegisters.clear(); - mReader->doregistersready = false; - } + if (pMainWindow->cpuDialog()!=nullptr && !mReader->signalReceived()) { +// if (mReader->doregistersready) { +// mRegisterModel->update(mReader->mRegisters); +// mReader->mRegisters.clear(); +// mReader->doregistersready = false; +// } - if (mReader->dodisassemblerready) { - pMainWindow->cpuDialog()->setDisassembly(mReader->mDisassembly); - mReader->mDisassembly.clear(); - mReader->dodisassemblerready = false; - } +// if (mReader->dodisassemblerready) { +// pMainWindow->cpuDialog()->setDisassembly(mReader->mDisassembly); +// mReader->mDisassembly.clear(); +// mReader->dodisassemblerready = false; +// } } - if (mReader->updateExecution()) { - if (mReader->currentCmd() && mReader->currentCmd()->source == DebugCommandSource::Console) { - pMainWindow->setActiveBreakpoint(mReader->breakPointFile(), mReader->breakPointLine(),false); - } else { - pMainWindow->setActiveBreakpoint(mReader->breakPointFile(), mReader->breakPointLine()); - } - refreshWatchVars(); // update variable information - } +// if (mReader->updateExecution()) { +// if (mReader->currentCmd() && mReader->currentCmd()->source == DebugCommandSource::Console) { +// pMainWindow->setActiveBreakpoint(mReader->breakPointFile(), mReader->breakPointLine(),false); +// } else { +// pMainWindow->setActiveBreakpoint(mReader->breakPointFile(), mReader->breakPointLine()); +// } +// refreshWatchVars(); // update variable information +// } if (mReader->signalReceived()) { @@ -588,475 +574,33 @@ DebugReader::DebugReader(Debugger* debugger, QObject *parent) : QThread(parent), mInvalidateAllVars = false; } -void DebugReader::postCommand(const QString &Command, const QString &Params, bool UpdateWatch, bool ShowInConsole, DebugCommandSource Source) +void DebugReader::postCommand(const QString &Command, const QString &Params, + DebugCommandSource Source) { QMutexLocker locker(&mCmdQueueMutex); - if (mCmdQueue.isEmpty() && UpdateWatch) { - emit pauseWatchUpdate(); - mUpdateCount++; - } PDebugCommand pCmd = std::make_shared(); pCmd->command = Command; pCmd->params = Params; - pCmd->updateWatch = UpdateWatch; - pCmd->showInConsole = ShowInConsole; pCmd->source = Source; mCmdQueue.enqueue(pCmd); // if (!mCmdRunning) -// runNextCmd(); + // runNextCmd(); +} + +void DebugReader::registerInferiorStoppedCommand(const QString &Command, const QString &Params) +{ + QMutexLocker locker(&mCmdQueueMutex); + PDebugCommand pCmd = std::make_shared(); + pCmd->command = Command; + pCmd->params = Params; + pCmd->source = DebugCommandSource::Other; + mInferiorStoppedHookCommands.append(pCmd); } void DebugReader::clearCmdQueue() { QMutexLocker locker(&mCmdQueueMutex); mCmdQueue.clear(); - - if (mUpdateCount>0) { - emit updateWatch(); - mUpdateCount=0; - } -} - -bool DebugReader::findAnnotation(AnnotationType annotation) -{ - AnnotationType NextAnnotation; - do { - NextAnnotation = getNextAnnotation(); - if (NextAnnotation == AnnotationType::TEOF) - return false; - } while (NextAnnotation != annotation); - - return true; -} - -AnnotationType DebugReader::getAnnotation(const QString &s) -{ - if (s == "pre-prompt") { - return AnnotationType::TPrePrompt; - } else if (s == "prompt") { - return AnnotationType::TPrompt; - } else if (s == "post-prompt") { - AnnotationType result = AnnotationType::TPostPrompt; - //hack to catch local - if ((mCurrentCmd) && (mCurrentCmd->command == "info locals")) { - result = AnnotationType::TLocal; - } else if ((mCurrentCmd) && (mCurrentCmd->command == "info args")) { - //hack to catch params - result = AnnotationType::TParam; - } else if ((mCurrentCmd) && (mCurrentCmd->command == "info") && (mCurrentCmd->params=="registers")) { - // Hack fix to catch register dump - result = AnnotationType::TInfoReg; - } else if ((mCurrentCmd) && (mCurrentCmd->command == "disas")) { - // Another hack to catch assembler - result = AnnotationType::TInfoAsm; - } else if ((mCurrentCmd) && (mCurrentCmd->command.startsWith("x/"))) { - result = AnnotationType::TMemory; - } - return result; - } else if (s == "error-begin") { - return AnnotationType::TErrorBegin; - } else if (s == "error-end") { - return AnnotationType::TErrorEnd; - } else if (s == "display-begin") { - return AnnotationType::TDisplayBegin; - } else if (s == "display-expression") { - return AnnotationType::TDisplayExpression; - } else if (s == "display-end") { - return AnnotationType::TDisplayEnd; - } else if (s == "frame-source-begin") { - return AnnotationType::TFrameSourceBegin; - } else if (s == "frame-source-file") { - return AnnotationType::TFrameSourceFile; - } else if (s == "frame-source-line") { - return AnnotationType::TFrameSourceLine; - } else if (s == "frame-function-name") { - return AnnotationType::TFrameFunctionName; - } else if (s == "frame-args") { - return AnnotationType::TFrameArgs; - } else if (s == "frame-begin") { - return AnnotationType::TFrameBegin; - } else if (s == "frame-end") { - return AnnotationType::TFrameEnd; - } else if (s == "frame-where") { - return AnnotationType::TFrameWhere; - } else if (s == "source") { - return AnnotationType::TSource; - } else if (s == "exited") { - return AnnotationType::TExit; - } else if (s == "arg-begin") { - return AnnotationType::TArgBegin; - } else if (s == "arg-name-end") { - return AnnotationType::TArgNameEnd; - } else if (s == "arg-value") { - return AnnotationType::TArgValue; - } else if (s == "arg-end") { - return AnnotationType::TArgEnd; - } else if (s == "array-section-begin") { - return AnnotationType::TArrayBegin; - } else if (s == "array-section-end") { - return AnnotationType::TArrayEnd; - } else if (s == "elt") { - return AnnotationType::TElt; - } else if (s == "elt-rep") { - return AnnotationType::TEltRep; - } else if (s == "elt-rep-end") { - return AnnotationType::TEltRepEnd; - } else if (s == "field-begin") { - return AnnotationType::TFieldBegin; - } else if (s == "field-name-end") { - return AnnotationType::TFieldNameEnd; - } else if (s == "field-value") { - return AnnotationType::TFieldValue; - } else if (s == "field-end") { - return AnnotationType::TFieldEnd; - } else if (s == "value-history-value") { - return AnnotationType::TValueHistoryValue; - } else if (s == "value-history-begin") { - return AnnotationType::TValueHistoryBegin; - } else if (s == "value-history-end") { - return AnnotationType::TValueHistoryEnd; - } else if (s == "signal") { - return AnnotationType::TSignal; - } else if (s == "signal-name") { - return AnnotationType::TSignalName; - } else if (s == "signal-name-end") { - return AnnotationType::TSignalNameEnd; - } else if (s == "signal-string") { - return AnnotationType::TSignalString; - } else if (s == "signal-string-end") { - return AnnotationType::TSignalStringEnd; - } else if (mIndex >= mOutput.length()) { - return AnnotationType::TEOF; - } else { - return AnnotationType::TUnknown;; - } -} - -AnnotationType DebugReader::getLastAnnotation(const QByteArray &text) -{ - int curpos = text.length()-1; - // Walk back until end of #26's - while ((curpos >= 0) && (text[curpos] != 26)) - curpos--; - - curpos++; - - // Tiny rewrite of GetNextWord for special purposes - QString s = ""; - while ((curpos < text.length()) && (text[curpos]>32)) { - s = s + text[curpos]; - curpos++; - } - - return getAnnotation(s); -} - -AnnotationType DebugReader::getNextAnnotation() -{ - // Skip until end of #26's, i.e. GDB formatted output - skipToAnnotation(); - - // Get part this line, after #26#26 - return getAnnotation(getNextWord()); -} - -bool DebugReader::outputTerminated(QByteArray &text) -{ - QStringList lines = textToLines(QString::fromUtf8(text)); - foreach (const QString& line,lines) { - if (line == "(gdb)") - return true; - } - return false; -} - -QString DebugReader::getNextFilledLine() -{ - // Walk up to an enter sequence - while (mIndex=mOutput.length()) - return ""; - // Skip ONE enter sequence (CRLF, CR, LF, etc.) - if ((mOutput[mIndex] == '\r') && (mIndex+132) { - Result += mOutput[mIndex]; - mIndex++; - } - return Result; -} - -QString DebugReader::getRemainingLine() -{ - QString Result; - - // Return part of line still ahead of us - while (mIndexfindWatchVar(watchName); - if (watchVar) { - // Advance up to the value - if (!findAnnotation(AnnotationType::TDisplayExpression)) - return;; - // Refresh GDB index so we can undisplay this by index - watchVar->gdbIndex = s.toInt(); - mDebugger->notifyBeforeProcessWatchVar(); - processWatchOutput(watchVar); - mDebugger->notifyAfterProcessWatchVar(); - //mDebugger->notifyWatchVarUpdated(watchVar); - } -} - -void DebugReader::handleError() -{ - QString s = getNextLine(); // error text - if (s.startsWith("Cannot find bounds of current function")) { - //We have exited - handleExit(); - } else if (s.startsWith("No symbol \"")) { - int head = s.indexOf('\"'); - int tail = s.lastIndexOf('\"'); - QString watchName = s.mid(head+1, tail-head-1); - - // Update current.. - mDebugger->invalidateWatchVar(watchName); - } -} - -void DebugReader::handleExit() -{ - doprocessexited=true; -} - -void DebugReader::handleLocalOutput() -{ - // name(spaces)hexvalue(tab)decimalvalue - QString s = getNextFilledLine(); - - bool nobreakLine = false; - QString line; - while (true) { - if (!s.startsWith("\032\032")) { - s = trimLeft(s); - if (s == "No locals.") { - return; - } - if (s == "No arguments.") { - return; - } - //todo: update local view - if (nobreakLine && pMainWindow->txtLocals()->document()->lineCount()>0) { - line += s; -// emit addLocalWithoutLinebreak(s); - } else { - mLocalsValue.append(line); - line = s; - } - nobreakLine=false; - } else { - nobreakLine = true; - } - s = getNextLine(); - if (!nobreakLine && s.isEmpty()) - break; - } - if (!line.isEmpty()) { - mLocalsValue.append(line); - } -} - -void DebugReader::handleLocals() -{ - mLocalsValue.clear(); - handleLocalOutput(); -} - -void DebugReader::handleMemory() -{ - doupdatememoryview = true; - // name(spaces)hexvalue(tab)decimalvalue - mMemoryValue.clear(); - QString s = getNextFilledLine(); - bool isAnnotation = false; - while (true) { - if (!s.startsWith("\032\032")) { - s = s.trimmed(); - if (!s.isEmpty()) { - mMemoryValue.append(s); - } - isAnnotation = false; - } else { - isAnnotation = true; - } - s = getNextLine(); - if (!isAnnotation && s.isEmpty()) - break; - } -} - -void DebugReader::handleParams(){ - handleLocalOutput(); - doupdatelocal = true; -} - -void DebugReader::handleRegisters() -{ - // name(spaces)hexvalue(tab)decimalvalue - QString s = getNextFilledLine(); - - while (true) { - PRegister reg = std::make_shared(); - // Cut name from 1 to first space - int x = s.indexOf(' '); - reg->name = s.mid(0,x); - s.remove(0,x); - // Remove spaces - s = trimLeft(s); - - // Cut hex value from 1 to first tab - x = s.indexOf('\t'); - if (x<0) - x = s.indexOf(' '); - reg->hexValue = s.mid(0,x); - s.remove(0,x); // delete tab too - s = trimLeft(s); - - // Remaining part contains decimal value - reg->decValue = s; - - if (!reg->name.trimmed().isEmpty()) - mRegisters.append(reg); - s = getNextLine(); - if (s.isEmpty()) - break; - } - - doregistersready = true; -} - -void DebugReader::handleSignal() -{ - mSignal = getNextFilledLine(); // Program received signal - - if (!findAnnotation(AnnotationType::TSignalName)) - return; - - mSignal = mSignal + getNextFilledLine(); // signal code - - if (!findAnnotation(AnnotationType::TSignalNameEnd)) - return; - - mSignal = mSignal + getNextFilledLine(); // comma - - if (!findAnnotation(AnnotationType::TSignalString)) - return; - - mSignal = mSignal + getNextFilledLine(); // user friendly description - - if (!findAnnotation(AnnotationType::TSignalStringEnd)) - return; - - mSignal = mSignal + getNextFilledLine(); // period - - doreceivedsignal = true; -} - -void DebugReader::handleSource() -{ - // source filename:line:offset:beg/middle/end:addr - QString s = trimLeft(getRemainingLine()); - - // remove offset, beg/middle/end, address - for (int i=0;i<3;i++) { - int delimPos = s.lastIndexOf(':'); - if (delimPos >= 0) - s.remove(delimPos,INT_MAX); - else - return; // Wrong format. Don't bother to continue - } - - // get line - int delimPos = s.lastIndexOf(':'); - if (delimPos >= 0) { - mBreakPointLine = s.mid(delimPos+1).toInt(); - s.remove(delimPos, INT_MAX); - } - - // get file - mBreakPointFile = s; - - doupdateexecution = true; - doupdatecpuwindow = true; -} - -void DebugReader::handleValueHistoryValue() -{ - mEvalValue = processEvalOutput(); - doevalready = true; } void DebugReader::processConsoleOutput(const QByteArray& line) @@ -1068,7 +612,6 @@ void DebugReader::processConsoleOutput(const QByteArray& line) void DebugReader::processResult(const QByteArray &result) { - int pos = result.indexOf('='); GDBMIResultParser parser; GDBMIResultType resultType; GDBMIResultParser::ParseValue parseValue; @@ -1094,35 +637,6 @@ void DebugReader::processResult(const QByteArray &result) return; } - QByteArray name = result.mid(0,pos); - QByteArray value = result.mid(pos+1); - if (name == "bkpt") { - // info about breakpoint - handleBreakpoint(value); - } else if (name == "BreakpointTable") { - // info about breakpoint table - handleBreakpointTable(value); - } else if (name == "stack") { - // info about frame stack - handleFrameStack(value); - } else if (name == "variables") { - // info about local variables & arguments - handleVariables(value); - } else if (name == "frame") { - // info about current selected frame - handleFrame(value); - } else if (name == "asm_insns") { - // info about disassembled codes - handleDisassembled(value); - } else if (name == "value") { - handleEval(value); - } else if (name=="register-names") { - handleRegisterNames(value); - } else if (name == "register-values") { - handleRegisterValues(value); - } else if (name == "memory") { - handleMemory(value); - } } void DebugReader::processExecAsyncRecord(const QByteArray &line) @@ -1132,12 +646,16 @@ void DebugReader::processExecAsyncRecord(const QByteArray &line) GDBMIResultParser parser; if (!parser.parseAsyncResult(line,result,multiValues)) return; + qDebug()<source == DebugCommandSource::Console) + emit inferiorStopped(mCurrentFile, mCurrentLine,false); + else + emit inferiorStopped(mCurrentFile, mCurrentLine,true); } } @@ -1208,31 +738,17 @@ void DebugReader::processDebugOutput(const QByteArray& debugOutput) emit parseStarted(); mConsoleOutput.clear(); - mLocalsValue.clear(); - mEvalValue.clear(); - mMemoryValue.clear(); + mFullOutput.clear(); - mUpdateExecution = false; mSignalReceived = false; mUpdateCPUInfo = false; - mUpdateLocals = false; - mEvalReady = false; mReceivedSFWarning = false; - dodisassemblerready = false; - doregistersready = false; - doevalready = false; - doupdatememoryview = false; - doupdatelocal = false; - doupdateexecution = false; - doreceivedsignal = false; - doupdatecpuwindow = false; - doreceivedsfwarning = false; - QList lines = splitByteArrayToLines(debugOutput); for (int i=0;iupdateWatch)) { - doUpdate=true; - if (mUpdateCount>0) { - mUpdateCount=0; - } - emit cmdFinished(); - } - return; - } if (mCurrentCmd) { mCurrentCmd.reset(); + emit cmdFinished(); } + if (mCmdQueue.isEmpty()) + return; PDebugCommand pCmd = mCmdQueue.dequeue(); mCmdRunning = true; mCurrentCmd = pCmd; - if (mCurrentCmd->updateWatch) - emit cmdStarted(); + emit cmdStarted(); QByteArray s; s=pCmd->command.toLocal8Bit(); @@ -1485,20 +993,12 @@ void DebugReader::runNextCmd() } // if devDebugger.ShowCommandLog or pCmd^.ShowInConsole then begin - if (pSettings->debugger().showCommandLog() || pCmd->showInConsole) { + if (pSettings->debugger().showCommandLog() ) { //update debug console - // if not devDebugger.ShowAnnotations then begin if (!pSettings->debugger().showAnnotations()) { -// if MainForm.DebugOutput.Lines.Count>0 then begin -// MainForm.DebugOutput.Lines.Delete(MainForm.DebugOutput.Lines.Count-1); -// end; emit changeDebugConsoleLastLine("(gdb)"+pCmd->command + ' ' + pCmd->params); -// MainForm.DebugOutput.Lines.Add('(gdb)'+pCmd^.Cmd + ' ' + pCmd^.params); -// MainForm.DebugOutput.Lines.Add(''); } else { emit changeDebugConsoleLastLine("(gdb)"+pCmd->command + ' ' + pCmd->params); -// MainForm.DebugOutput.Lines.Add(pCmd^.Cmd + ' ' + pCmd^.params); -// MainForm.DebugOutput.Lines.Add(''); } } } @@ -1599,6 +1099,16 @@ QStringList DebugReader::tokenize(const QString &s) return result; } +bool DebugReader::outputTerminated(const QByteArray &text) +{ + QStringList lines = textToLines(QString::fromUtf8(text)); + foreach (const QString& line,lines) { + if (line.trimmed() == "(gdb)") + return true; + } + return false; +} + void DebugReader::handleBreakpoint(const GDBMIResultParser::ParseObject& breakpoint) { // gdb use system encoding for file path @@ -1670,41 +1180,16 @@ QByteArray DebugReader::removeToken(const QByteArray &line) return line; } +const QStringList &DebugReader::fullOutput() const +{ + return mFullOutput; +} + bool DebugReader::receivedSFWarning() const { return mReceivedSFWarning; } -const QStringList &DebugReader::memoryValue() const -{ - return mMemoryValue; -} - -bool DebugReader::updateMemory() const -{ - return mUpdateMemory; -} - -const QString &DebugReader::evalValue() const -{ - return mEvalValue; -} - -bool DebugReader::evalReady() const -{ - return mEvalReady; -} - -const QStringList &DebugReader::localsValue() const -{ - return mLocalsValue; -} - -bool DebugReader::updateLocals() const -{ - return mUpdateLocals; -} - bool DebugReader::updateCPUInfo() const { return mUpdateCPUInfo; @@ -1715,16 +1200,6 @@ const PDebugCommand &DebugReader::currentCmd() const return mCurrentCmd; } -const QString &DebugReader::breakPointFile() const -{ - return mBreakPointFile; -} - -int DebugReader::breakPointLine() const -{ - return mBreakPointLine; -} - const QStringList &DebugReader::consoleOutput() const { return mConsoleOutput; @@ -1735,21 +1210,11 @@ bool DebugReader::signalReceived() const return mSignalReceived; } -bool DebugReader::updateExecution() const -{ - return mUpdateExecution; -} - bool DebugReader::processExited() const { return mProcessExited; } -bool DebugReader::inferiorPaused() const -{ - return mInferiorPaused; -} - bool DebugReader::invalidateAllVars() const { return mInvalidateAllVars; @@ -1780,7 +1245,7 @@ bool DebugReader::commandRunning() return !mCmdQueue.isEmpty(); } -bool DebugReader::waitStart() +void DebugReader::waitStart() { mStartSemaphore.acquire(1); } @@ -1843,8 +1308,7 @@ void DebugReader::run() readed = mProcess->readAll(); buffer += readed; - - if ( readed.endsWith("\r\n")&& outputTerminated(buffer)) { + if ( readed.endsWith("\n")&& outputTerminated(buffer)) { processDebugOutput(buffer); buffer.clear(); mCmdRunning = false; diff --git a/RedPandaIDE/debugger.h b/RedPandaIDE/debugger.h index a1674274..fb56cb37 100644 --- a/RedPandaIDE/debugger.h +++ b/RedPandaIDE/debugger.h @@ -23,8 +23,6 @@ enum class DebugCommandSource { struct DebugCommand{ QString command; QString params; - bool updateWatch; - bool showInConsole; DebugCommandSource source; }; @@ -176,8 +174,6 @@ public: // Play/pause bool start(); void sendCommand(const QString& command, const QString& params, - bool updateWatch = true, - bool showInConsole = false, DebugCommandSource source = DebugCommandSource::Other); bool commandRunning(); @@ -267,14 +263,14 @@ class DebugReader : public QThread Q_OBJECT public: explicit DebugReader(Debugger* debugger, QObject *parent = nullptr); - void postCommand(const QString &Command, const QString &Params, - bool UpdateWatch, bool ShowInConsole, DebugCommandSource Source); + void postCommand(const QString &Command, const QString &Params, DebugCommandSource Source); + void registerInferiorStoppedCommand(const QString &Command, const QString &Params); QString debuggerPath() const; void setDebuggerPath(const QString &debuggerPath); void stopDebug(); bool commandRunning(); - bool waitStart(); + void waitStart(); bool invalidateAllVars() const; void setInvalidateAllVars(bool invalidateAllVars); @@ -283,8 +279,6 @@ public: bool processExited() const; - bool updateExecution() const; - bool signalReceived() const; const QStringList &consoleOutput() const; @@ -311,13 +305,13 @@ public: bool receivedSFWarning() const; + const QStringList &fullOutput() const; + signals: void parseStarted(); void invalidateAllVars(); void parseFinished(); void writeToDebugFailed(); - void pauseWatchUpdate(); - void updateWatch(); void processError(QProcess::ProcessError error); void changeDebugConsoleLastLine(const QString& text); void cmdStarted(); @@ -325,32 +319,19 @@ signals: void breakpointInfoGetted(const QString& filename, int line, int number); void inferiorContinued(); - void inferiorStopped(const QString& filename, int line); + void inferiorStopped(const QString& filename, int line, bool setFocus); void localsUpdated(const QStringList& localsValue); void evalUpdated(const QString& value); void memoryUpdated(const QStringList& memoryValues); private: void clearCmdQueue(); - bool outputTerminated(QByteArray& text); - void handleDisassembly(); - void handleDisplay(); - void handleError(); - void handleExit(); - void handleLocalOutput(); - void handleLocals(); - void handleMemory(); - void handleParams(); - void handleRegisters(); - void handleSignal(); - void handleSource(); - void handleValueHistoryValue(); - QString processEvalOutput(); void processWatchOutput(PWatchVar WatchVar); void runNextCmd(); QStringList tokenize(const QString& s); + bool outputTerminated(const QByteArray& text); void handleBreakpoint(const GDBMIResultParser::ParseObject& breakpoint); void handleStack(const QList & stack); void handleLocalVariables(const QList & variables); @@ -362,6 +343,7 @@ private: void processError(const QByteArray& errorLine); void processResultRecord(const QByteArray& line); void processDebugOutput(const QByteArray& debugOutput); + void runInferiorStoppedHook(); QByteArray removeToken(const QByteArray& line); private: Debugger *mDebugger; @@ -369,7 +351,6 @@ private: QRecursiveMutex mCmdQueueMutex; QSemaphore mStartSemaphore; QQueue mCmdQueue; - int mUpdateCount; bool mInvalidateAllVars; //fOnInvalidateAllVars: TInvalidateAllVarsEvent; @@ -396,19 +377,19 @@ private: bool doupdatememoryview; // + QList mInferiorStoppedHookCommands; bool mInferiorRunning; bool mProcessExited; - bool mUpdateExecution; bool mSignalReceived; bool mUpdateCPUInfo; bool mReceivedSFWarning; + int mCurrentLine; + int mCurrentAddress; + QString mCurrentFile; QStringList mConsoleOutput; - int mBreakPointLine; - QString mBreakPointFile; - - + QStringList mFullOutput; bool mStop; // QThread interface protected: diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index a27d939a..de4c378e 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -2826,7 +2826,7 @@ void Editor::showDebugHint(const QString &s, int line) connect(pMainWindow->debugger(), &Debugger::evalValueReady, this, &Editor::onTipEvalValueReady); mCurrentDebugTipWord = s; - pMainWindow->debugger()->sendCommand("print",s,false); + pMainWindow->debugger()->sendCommand("print",s); } QString Editor::getErrorHint(const PSyntaxIssue& issue) diff --git a/RedPandaIDE/gdbmiresultparser.cpp b/RedPandaIDE/gdbmiresultparser.cpp index cba4e8a3..54a49104 100644 --- a/RedPandaIDE/gdbmiresultparser.cpp +++ b/RedPandaIDE/gdbmiresultparser.cpp @@ -2,6 +2,7 @@ #include #include +#include GDBMIResultParser::GDBMIResultParser() { @@ -38,17 +39,20 @@ bool GDBMIResultParser::parseAsyncResult(const QByteArray &record, QByteArray &r if (*p!='*') return false; p++; - const char* start; + const char* start=p; while (*p && *p!=',') p++; result = QByteArray(start,p-start); if (*p==0) return true; + p++; return parseMultiValues(p,multiValue); } bool GDBMIResultParser::parseMultiValues(const char* p, ParseObject &multiValue) { + qDebug()<<"-------"; + qDebug()< array; + QList array; result = parseArray(p,array); value = array; break; @@ -113,8 +119,6 @@ bool GDBMIResultParser::parseValue(const char *&p, ParseValue &value) if (!result) return false; skipSpaces(p); - if (*p!=0 && *p!=',') - return false; return true; } @@ -123,18 +127,85 @@ bool GDBMIResultParser::parseStringValue(const char *&p, QByteArray& stringValue if (*p!='"') return false; p++; - const char* valueStart = p; + stringValue.clear(); while (*p!=0) { if (*p == '"') { break; } else if (*p=='\\' && *(p+1)!=0) { - p+=2; + p++; + switch (*p) { + case '\'': + stringValue+=0x27; + p++; + break; + case '"': + stringValue+=0x22; + p++; + break; + case '?': + stringValue+=0x3f; + p++; + break; + case '\\': + stringValue+=0x5c; + p++; + break; + case 'a': + stringValue+=0x07; + p++; + break; + case 'b': + stringValue+=0x08; + p++; + break; + case 'f': + stringValue+=0x0c; + p++; + break; + case 'n': + stringValue+=0x0a; + p++; + break; + case 'r': + stringValue+=0x0d; + p++; + break; + case 't': + stringValue+=0x09; + p++; + break; + case 'v': + stringValue+=0x0b; + p++; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + { + int i=0; + for (i=0;i<3;i++) { + if (*(p+i)<'0' || *(p+i)>'7') + break; + } + QByteArray numStr(p,i); + bool ok; + unsigned char ch = numStr.toInt(&ok,8); + stringValue+=ch; + p+=i; + break; + } + } } else { + stringValue+=*p; p++; } } if (*p=='"') { - stringValue = QByteArray(valueStart,p-valueStart); p++; //skip '"' return true; } @@ -152,6 +223,7 @@ bool GDBMIResultParser::parseObject(const char *&p, ParseObject &obj) QByteArray propName; ParseValue propValue; bool result = parseNameAndValue(p,propName,propValue); + qDebug()< &array): { } +GDBMIResultParser::ParseValue::ParseValue(const ParseValue &value): + mValue(value.mValue), + mArray(value.mArray), + mObject(value.mObject), + mType(value.mType) +{ +} + +GDBMIResultParser::ParseValue &GDBMIResultParser::ParseValue::operator=(const GDBMIResultParser::ParseValue &value) +{ + mType = value.mType; + mValue = value.mValue; + mArray = value.mArray; + mObject = value.mObject; + return *this; +} + GDBMIResultParser::ParseValue &GDBMIResultParser::ParseValue::operator=(const QByteArray &value) { Q_ASSERT(mType == ParseValueType::NotAssigned); mType = ParseValueType::Value; mValue = value; + return *this; } GDBMIResultParser::ParseValue &GDBMIResultParser::ParseValue::operator=(const ParseObject& object) @@ -306,6 +413,7 @@ GDBMIResultParser::ParseValue &GDBMIResultParser::ParseValue::operator=(const Pa Q_ASSERT(mType == ParseValueType::NotAssigned); mType = ParseValueType::Object; mObject = object; + return *this; } GDBMIResultParser::ParseValue &GDBMIResultParser::ParseValue::operator=(const QList& array) @@ -313,19 +421,34 @@ GDBMIResultParser::ParseValue &GDBMIResultParser::ParseValue::operator=(const QL Q_ASSERT(mType == ParseValueType::NotAssigned); mType = ParseValueType::Array; mArray = array; + return *this; } -const GDBMIResultParser::ParseValue GDBMIResultParser::ParseObject::operator[](const QByteArray &name) const +GDBMIResultParser::ParseObject::ParseObject() { - if (mProps.contains(name)) - return mProps[name]; + +} + +GDBMIResultParser::ParseObject::ParseObject(const ParseObject &object): + mProps(object.mProps) +{ + +} + +GDBMIResultParser::ParseValue GDBMIResultParser::ParseObject::operator[](const QByteArray &name) const +{ + if (mProps.contains(name)) { + ParseValue value(mProps[name]); + return value; + } return ParseValue(); } GDBMIResultParser::ParseObject &GDBMIResultParser::ParseObject::operator=(const ParseObject &object) { mProps = object.mProps; + return *this; } GDBMIResultParser::ParseValue &GDBMIResultParser::ParseObject::operator[](const QByteArray &name) { diff --git a/RedPandaIDE/gdbmiresultparser.h b/RedPandaIDE/gdbmiresultparser.h index a895c73f..13e0977c 100644 --- a/RedPandaIDE/gdbmiresultparser.h +++ b/RedPandaIDE/gdbmiresultparser.h @@ -36,7 +36,9 @@ public: class ParseObject { public: - const ParseValue operator[](const QByteArray& name) const; + explicit ParseObject(); + ParseObject(const ParseObject& object); + ParseValue operator[](const QByteArray& name) const; ParseValue& operator[](const QByteArray& name); ParseObject& operator=(const ParseObject& object); private: @@ -49,13 +51,16 @@ public: explicit ParseValue(const QByteArray& value); explicit ParseValue(const ParseObject &object); explicit ParseValue(const QList& array); - ParseValue(const ParseValue&) = delete; + ParseValue(const ParseValue& value); const QByteArray &value() const; const QList &array() const; const ParseObject &object() const; int intValue(int defaultValue=-1) const; + int hexValue(int defaultValue=-1) const; + QString pathValue() const; ParseValueType type() const; + bool isValid() const; ParseValue& operator=(const QByteArray& value); ParseValue& operator=(const ParseObject& object); ParseValue& operator=(const QList& array); diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index f24511cf..cd609b8b 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -1444,11 +1444,9 @@ void MainWindow::debug() return; case CompileTarget::File: mDebugger->sendCommand("-exec-run", "--start"); - mDebugger->updateDebugInfo(); break; case CompileTarget::Project: mDebugger->sendCommand("-exec-run", "--start"); - mDebugger->updateDebugInfo(); break; default: break; @@ -1459,11 +1457,9 @@ void MainWindow::debug() return; case CompileTarget::File: mDebugger->sendCommand("-exec-run",""); - mDebugger->updateDebugInfo(); break; case CompileTarget::Project: mDebugger->sendCommand("-exec-run",""); - mDebugger->updateDebugInfo(); break; default: break; @@ -3698,7 +3694,7 @@ void MainWindow::cleanUpCPUDialog() void MainWindow::onDebugCommandInput(const QString& command) { if (mDebugger->executing()) { - mDebugger->sendCommand(command,"",true,true); + mDebugger->sendCommand(command,""); } } @@ -3978,8 +3974,6 @@ void MainWindow::on_actionStep_Over_triggered() //WatchView.Items.BeginUpdate(); mDebugger->invalidateAllVars(); mDebugger->sendCommand("-exec-next", ""); - mDebugger->updateDebugInfo(); - mDebugger->refreshWatchVars(); } } @@ -3989,8 +3983,6 @@ void MainWindow::on_actionStep_Into_triggered() //WatchView.Items.BeginUpdate(); mDebugger->invalidateAllVars(); mDebugger->sendCommand("-exec-step", ""); - mDebugger->updateDebugInfo(); - mDebugger->refreshWatchVars(); } } @@ -4001,8 +3993,6 @@ void MainWindow::on_actionStep_Out_triggered() //WatchView.Items.BeginUpdate(); mDebugger->invalidateAllVars(); mDebugger->sendCommand("-exec-finish", ""); - mDebugger->updateDebugInfo(); - mDebugger->refreshWatchVars(); } } @@ -4014,10 +4004,9 @@ void MainWindow::on_actionRun_To_Cursor_triggered() if (e!=nullptr) { //WatchView.Items.BeginUpdate(); mDebugger->invalidateAllVars(); - mDebugger->sendCommand("-break-insert", QString("-t --line %1").arg(e->caretY())); - mDebugger->sendCommand("-exec-continue", ""); - mDebugger->updateDebugInfo(); - mDebugger->refreshWatchVars(); + mDebugger->sendCommand("-exec-until", QString("\"%1\":%2") + .arg(e->filename()) + .arg(e->caretY())); } } @@ -4079,7 +4068,7 @@ void MainWindow::onDebugEvaluateInput() if (!s.isEmpty()) { connect(mDebugger, &Debugger::evalValueReady, this, &MainWindow::onEvalValueReady); - mDebugger->sendCommand("print",s,false); + mDebugger->sendCommand("print",s); } } @@ -4089,7 +4078,7 @@ void MainWindow::onDebugMemoryAddressInput() if (!s.isEmpty()) { connect(mDebugger, &Debugger::memoryExamineReady, this, &MainWindow::onMemoryExamineReady); - mDebugger->sendCommand("-data-read-memory/64bx",s,false); + mDebugger->sendCommand("-data-read-memory/64bx",s); } } diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index 4e0383b4..39550f94 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -101,7 +101,6 @@ public: QFileSystemWatcher* fileSystemWatcher(); void removeActiveBreakpoints(); - void setActiveBreakpoint(QString FileName, int Line, bool setFocus=true); void updateAppTitle(); void addDebugOutput(const QString& text); void changeDebugOutputLastline(const QString& text); @@ -193,6 +192,7 @@ public slots: void onTodoParseStarted(const QString& filename); void onTodoParsing(const QString& filename, int lineNo, int ch, const QString& line); void onTodoParseFinished(); + void setActiveBreakpoint(QString FileName, int Line, bool setFocus); private: void prepareProjectForCompile(); diff --git a/RedPandaIDE/qsynedit/SynEdit.cpp b/RedPandaIDE/qsynedit/SynEdit.cpp index 29f3c88d..2420b0f5 100644 --- a/RedPandaIDE/qsynedit/SynEdit.cpp +++ b/RedPandaIDE/qsynedit/SynEdit.cpp @@ -1819,7 +1819,7 @@ void SynEdit::doDeleteLastChar() mLines->deleteAt(mCaretY); doLinesDeleted(mCaretY+1, 1); if (mOptions.testFlag(eoTrimTrailingSpaces)) - Temp = TrimRight(Temp); + Temp = trimRight(Temp); setLineText(lineText() + Temp); helper = lineBreak(); //"/r/n" } @@ -2153,7 +2153,7 @@ void SynEdit::insertLine(bool moveCaret) rightLineText,mOptions.testFlag(eoAutoIndent) && notInComment); if (mOptions.testFlag(eoAutoIndent)) { - rightLineText=TrimLeft(rightLineText); + rightLineText=trimLeft(rightLineText); } QString indentSpacesForRightLineText = GetLeftSpacing(indentSpaces,true); mLines->insert(mCaretY, indentSpacesForRightLineText+rightLineText); @@ -2670,7 +2670,7 @@ void SynEdit::doAddChar(QChar AChar) if (line.length() < oldCaretX) { int indentSpaces = calcIndentSpaces(oldCaretY,line+":", true); if (indentSpaces != leftSpaces(line)) { - QString newLine = GetLeftSpacing(indentSpaces,true) + TrimLeft(line); + QString newLine = GetLeftSpacing(indentSpaces,true) + trimLeft(line); int i = newLine.length(); mLines->putString(oldCaretY-1,newLine); internalSetCaretXY(BufferCoord{i+1,oldCaretY}); @@ -4965,7 +4965,7 @@ void SynEdit::doLinesInserted(int firstLine, int count) void SynEdit::properSetLine(int ALine, const QString &ALineText, bool notify) { if (mOptions.testFlag(eoTrimTrailingSpaces)) { - mLines->putString(ALine,TrimRight(ALineText),notify); + mLines->putString(ALine,trimRight(ALineText),notify); } else { mLines->putString(ALine,ALineText,notify); } @@ -5077,7 +5077,7 @@ int SynEdit::insertTextByNormalMode(const QString &Value) int startLine = mCaretY; sLeftSide = lineText().mid(0, mCaretX - 1); if (mCaretX - 1 > sLeftSide.length()) { - if (StringIsBlank(sLeftSide)) + if (stringIsBlank(sLeftSide)) sLeftSide = GetLeftSpacing(displayX() - 1, true); else sLeftSide += QString(mCaretX - 1 - sLeftSide.length(),' '); @@ -5093,7 +5093,7 @@ int SynEdit::insertTextByNormalMode(const QString &Value) Start = 0; P = GetEOL(Value,Start); if (P Date: Wed, 24 Nov 2021 21:22:01 +0800 Subject: [PATCH 14/32] work save --- RedPandaIDE/debugger.cpp | 50 ++++++++++++++------- RedPandaIDE/debugger.h | 16 ++----- RedPandaIDE/gdbmiresultparser.cpp | 26 +++++++---- RedPandaIDE/icons.qrc | 1 + RedPandaIDE/images/newlook24/093-pause.png | Bin 0 -> 1709 bytes RedPandaIDE/mainwindow.cpp | 27 +++++++---- RedPandaIDE/mainwindow.h | 2 + RedPandaIDE/mainwindow.ui | 14 ++++++ 8 files changed, 89 insertions(+), 47 deletions(-) create mode 100644 RedPandaIDE/images/newlook24/093-pause.png diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index b2df715a..80903ef4 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -65,6 +65,7 @@ bool Debugger::start() connect(mReader, &DebugReader::changeDebugConsoleLastLine,this,&Debugger::onChangeDebugConsoleLastline); connect(mReader, &DebugReader::cmdStarted,pMainWindow, &MainWindow::disableDebugActions); connect(mReader, &DebugReader::cmdFinished,pMainWindow, &MainWindow::enableDebugActions); + connect(mReader, &DebugReader::inferiorStopped, pMainWindow, &MainWindow::enableDebugActions); connect(mReader, &DebugReader::breakpointInfoGetted, mBreakpointModel, &BreakpointModel::updateBreakpointNumber); @@ -76,9 +77,13 @@ bool Debugger::start() connect(mReader, &DebugReader::evalUpdated,[this](const QString& value) { emit evalValueReady(value); }); + connect(mReader, &DebugReader::inferiorContinued,pMainWindow, + &MainWindow::removeActiveBreakpoints); connect(mReader, &DebugReader::inferiorStopped,pMainWindow, &MainWindow::setActiveBreakpoint); + mReader->registerInferiorStoppedCommand("-stack-list-frames",""); + mReader->registerInferiorStoppedCommand("-stack-list-variables", "--all-values"); mReader->start(); mReader->waitStart(); @@ -153,6 +158,14 @@ bool Debugger::commandRunning() return false; } +bool Debugger::inferiorRunning() +{ + if (mExecuting && mReader) { + return mReader->inferiorRunning(); + } + return false; +} + void Debugger::addBreakpoint(int line, const Editor* editor) { addBreakpoint(line,editor->filename()); @@ -373,12 +386,6 @@ void Debugger::notifyAfterProcessWatchVar() mWatchModel->endUpdate(); } -void Debugger::updateDebugInfo() -{ - sendCommand("-stack-list-frames", ""); - sendCommand("-stack-list-variables", "--skip-unavailable --allvalues"); -} - bool Debugger::useUTF8() const { return mUseUTF8; @@ -461,11 +468,7 @@ void Debugger::syncFinishedParsing() } } - // The program to debug has stopped. Stop the debugger - if (mReader->processExited()) { - stop(); - return; - } + // show command output if (pSettings->debugger().showCommandLog() ) { @@ -480,6 +483,12 @@ void Debugger::syncFinishedParsing() } } + // The program to debug has stopped. Stop the debugger + if (mReader->processExited()) { + stop(); + return; + } + // Some part of the CPU form has been updated if (pMainWindow->cpuDialog()!=nullptr && !mReader->signalReceived()) { // if (mReader->doregistersready) { @@ -646,7 +655,6 @@ void DebugReader::processExecAsyncRecord(const QByteArray &line) GDBMIResultParser parser; if (!parser.parseAsyncResult(line,result,multiValues)) return; - qDebug()< & stack PTrace trace = std::make_shared(); trace->funcname = frameObject["func"].value(); trace->filename = frameObject["fullname"].pathValue(); - trace->line = frameObject["fullname"].intValue(); + trace->line = frameObject["line"].intValue(); trace->level = frameObject["level"].intValue(0); trace->address = frameObject["addr"].value(); mDebugger->backtraceModel()->addTrace(trace); @@ -1180,6 +1189,11 @@ QByteArray DebugReader::removeToken(const QByteArray &line) return line; } +bool DebugReader::inferiorRunning() const +{ + return mInferiorRunning; +} + const QStringList &DebugReader::fullOutput() const { return mFullOutput; @@ -1308,7 +1322,11 @@ void DebugReader::run() readed = mProcess->readAll(); buffer += readed; - if ( readed.endsWith("\n")&& outputTerminated(buffer)) { + if (!readed.isEmpty()) { + qDebug()<<"*******"; + qDebug()< mInferiorStoppedHookCommands; bool mInferiorRunning; diff --git a/RedPandaIDE/gdbmiresultparser.cpp b/RedPandaIDE/gdbmiresultparser.cpp index 54a49104..35d256fb 100644 --- a/RedPandaIDE/gdbmiresultparser.cpp +++ b/RedPandaIDE/gdbmiresultparser.cpp @@ -51,8 +51,6 @@ bool GDBMIResultParser::parseAsyncResult(const QByteArray &record, QByteArray &r bool GDBMIResultParser::parseMultiValues(const char* p, ParseObject &multiValue) { - qDebug()<<"-------"; - qDebug()<images/editor/bookmark.png images/newlook24/091-openproblemanswer.png images/newlook24/092-runallproblemcases.png + images/newlook24/093-pause.png diff --git a/RedPandaIDE/images/newlook24/093-pause.png b/RedPandaIDE/images/newlook24/093-pause.png new file mode 100644 index 0000000000000000000000000000000000000000..4394cb520d238ec454e2c3e0d60bd0b8bae4b78a GIT binary patch literal 1709 zcmcIlO>f*p7zUm(S$mA_ zWOpNRDTlTae*tkqZ~`uH;ZOwJ0f~<*zkmvHDJW8Ty<%a2a9CF?5Fzd3q^eEoB{Nr*?H}3%*>Xm*6Ai0+ z;nED~`=>*rXpYYEtwXRf)%#fDtTjrww!<@VkOq9~kjMGz%oq#idy|8-KlYRb8t?N6 zU>OL*b5luAgF{y=hVym|AM=LJW1vo*ubb(wDb> uzJ2}Nr%R=uF1`28Z@tpX%?m$n+?DW4uU-N7(`4#B^ literal 0 HcmV?d00001 diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index cd609b8b..bdb1e3a8 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -1410,6 +1410,9 @@ void MainWindow::debug() updateEditorActions(); return; } + mDebugger->sendCommand("-gdb-set","mi-async on"); + mDebugger->sendCommand("-gdb-set","target-async on"); + mDebugger->sendCommand("-gdb-show", "mi-async"); updateEditorActions(); @@ -3013,13 +3016,13 @@ void MainWindow::disableDebugActions() void MainWindow::enableDebugActions() { - ui->actionStep_Into->setEnabled(true); - ui->actionStep_Over->setEnabled(true); - ui->actionStep_Out->setEnabled(true); - ui->actionRun_To_Cursor->setEnabled(true); - ui->actionContinue->setEnabled(true); - ui->cbEvaluate->setEnabled(true); - ui->cbMemoryAddress->setEnabled(true); + ui->actionStep_Into->setEnabled(!mDebugger->inferiorRunning()); + ui->actionStep_Over->setEnabled(!mDebugger->inferiorRunning()); + ui->actionStep_Out->setEnabled(!mDebugger->inferiorRunning()); + ui->actionRun_To_Cursor->setEnabled(!mDebugger->inferiorRunning()); + ui->actionContinue->setEnabled(!mDebugger->inferiorRunning()); + ui->cbEvaluate->setEnabled(!mDebugger->inferiorRunning()); + ui->cbMemoryAddress->setEnabled(!mDebugger->inferiorRunning()); } void MainWindow::onTodoParseStarted(const QString&) @@ -4018,8 +4021,6 @@ void MainWindow::on_actionContinue_triggered() //WatchView.Items.BeginUpdate(); mDebugger->invalidateAllVars(); mDebugger->sendCommand("-exec-continue", ""); - mDebugger->updateDebugInfo(); - mDebugger->refreshWatchVars(); } } @@ -5742,3 +5743,11 @@ void MainWindow::on_actionDelete_to_BOL_triggered() } } + +void MainWindow::on_actionPause_triggered() +{ + if (mDebugger->executing()) { + mDebugger->sendCommand("-exec-interrupt","-a"); + } +} + diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index 39550f94..c6ad3f67 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -528,6 +528,8 @@ private slots: void on_actionDelete_to_BOL_triggered(); + void on_actionPause_triggered(); + private: Ui::MainWindow *ui; EditorList *mEditorList; diff --git a/RedPandaIDE/mainwindow.ui b/RedPandaIDE/mainwindow.ui index d45c3e17..987029a3 100644 --- a/RedPandaIDE/mainwindow.ui +++ b/RedPandaIDE/mainwindow.ui @@ -1424,6 +1424,7 @@ + @@ -1642,6 +1643,7 @@ + @@ -2649,6 +2651,18 @@ Ctrl+Backspace + + + + :/icons/images/newlook24/093-pause.png:/icons/images/newlook24/093-pause.png + + + Pause + + + F3 + + From de0f176284b4b756c83dbfcd2523bb0da4381030 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Wed, 24 Nov 2021 22:16:40 +0800 Subject: [PATCH 15/32] breakpoint / run / evaluation / memory view ok --- RedPandaIDE/debugger.cpp | 29 ++++++++++++++--------------- RedPandaIDE/editor.cpp | 2 +- RedPandaIDE/gdbmiresultparser.cpp | 29 ++++++++++++++--------------- RedPandaIDE/gdbmiresultparser.h | 4 ++-- RedPandaIDE/mainwindow.cpp | 17 ++--------------- RedPandaIDE/mainwindow.h | 2 -- RedPandaIDE/mainwindow.ui | 14 -------------- RedPandaIDE/widgets/cpudialog.cpp | 4 ++-- 8 files changed, 35 insertions(+), 66 deletions(-) diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index 80903ef4..9ce941da 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -623,8 +623,10 @@ void DebugReader::processResult(const QByteArray &result) { GDBMIResultParser parser; GDBMIResultType resultType; - GDBMIResultParser::ParseValue parseValue; - bool parseOk = parser.parse(result,resultType,parseValue); + GDBMIResultParser::ParseObject multiValues; + if (!mCurrentCmd) + return; + bool parseOk = parser.parse(result, mCurrentCmd->command, resultType,multiValues); if (!parseOk) return; switch(resultType) { @@ -633,16 +635,19 @@ void DebugReader::processResult(const QByteArray &result) case GDBMIResultType::Locals: break; case GDBMIResultType::Breakpoint: - handleBreakpoint(parseValue.object()); + handleBreakpoint(multiValues["bkpt"].object()); return; case GDBMIResultType::FrameStack: - handleStack(parseValue.array()); + handleStack(multiValues["stack"].array()); return; case GDBMIResultType::LocalVariables: - handleLocalVariables(parseValue.array()); + handleLocalVariables(multiValues["variables"].array()); return; case GDBMIResultType::Evaluation: - handleEvaluation(parseValue.value()); + handleEvaluation(multiValues["value"].value()); + return; + case GDBMIResultType::Memory: + handleMemory(multiValues["memory"].array()); return; } @@ -1005,9 +1010,9 @@ void DebugReader::runNextCmd() if (pSettings->debugger().showCommandLog() ) { //update debug console if (!pSettings->debugger().showAnnotations()) { - emit changeDebugConsoleLastLine("(gdb)"+pCmd->command + ' ' + pCmd->params); + emit changeDebugConsoleLastLine(pCmd->command + ' ' + pCmd->params); } else { - emit changeDebugConsoleLastLine("(gdb)"+pCmd->command + ' ' + pCmd->params); + emit changeDebugConsoleLastLine(pCmd->command + ' ' + pCmd->params); } } } @@ -1121,7 +1126,7 @@ bool DebugReader::outputTerminated(const QByteArray &text) void DebugReader::handleBreakpoint(const GDBMIResultParser::ParseObject& breakpoint) { // gdb use system encoding for file path - QString filename = breakpoint["fullname"].value(); + QString filename = breakpoint["fullname"].pathValue(); int line = breakpoint["line"].intValue(); int number = breakpoint["number"].intValue(); emit breakpointInfoGetted(filename, line , number); @@ -1322,10 +1327,6 @@ void DebugReader::run() readed = mProcess->readAll(); buffer += readed; - if (!readed.isEmpty()) { - qDebug()<<"*******"; - qDebug()<debugger(), &Debugger::evalValueReady, this, &Editor::onTipEvalValueReady); mCurrentDebugTipWord = s; - pMainWindow->debugger()->sendCommand("print",s); + pMainWindow->debugger()->sendCommand("-data-evaluate-expression",s); } QString Editor::getErrorHint(const PSyntaxIssue& issue) diff --git a/RedPandaIDE/gdbmiresultparser.cpp b/RedPandaIDE/gdbmiresultparser.cpp index 35d256fb..0ebc5157 100644 --- a/RedPandaIDE/gdbmiresultparser.cpp +++ b/RedPandaIDE/gdbmiresultparser.cpp @@ -6,30 +6,29 @@ GDBMIResultParser::GDBMIResultParser() { - mResultTypes.insert("bkpt",GDBMIResultType::Breakpoint); - mResultTypes.insert("BreakpointTable",GDBMIResultType::BreakpointTable); - mResultTypes.insert("stack",GDBMIResultType::FrameStack); - mResultTypes.insert("variables", GDBMIResultType::LocalVariables); - mResultTypes.insert("frame",GDBMIResultType::Frame); - mResultTypes.insert("asm_insns",GDBMIResultType::Disassembly); - mResultTypes.insert("value",GDBMIResultType::Evaluation); - mResultTypes.insert("register-names",GDBMIResultType::RegisterNames); - mResultTypes.insert("register-values",GDBMIResultType::RegisterValues); - mResultTypes.insert("memory",GDBMIResultType::Memory); + mResultTypes.insert("-break-insert",GDBMIResultType::Breakpoint); + //mResultTypes.insert("BreakpointTable",GDBMIResultType::BreakpointTable); + mResultTypes.insert("-stack-list-frames",GDBMIResultType::FrameStack); + mResultTypes.insert("-stack-list-variables", GDBMIResultType::LocalVariables); + //mResultTypes.insert("frame",GDBMIResultType::Frame); + mResultTypes.insert("-data-disassemble",GDBMIResultType::Disassembly); + mResultTypes.insert("-data-evaluate-expression",GDBMIResultType::Evaluation); +// mResultTypes.insert("register-names",GDBMIResultType::RegisterNames); +// mResultTypes.insert("register-values",GDBMIResultType::RegisterValues); + mResultTypes.insert("-data-read-memory",GDBMIResultType::Memory); } -bool GDBMIResultParser::parse(const QByteArray &record, GDBMIResultType &type, ParseValue& value) +bool GDBMIResultParser::parse(const QByteArray &record, const QString& command, GDBMIResultType &type, ParseObject& multiValues) { const char* p = record.data(); - QByteArray name; - bool result = parseNameAndValue(p,name,value); + bool result = parseMultiValues(p,multiValues); if (!result) return false; // if (*p!=0) // return false; - if (!mResultTypes.contains(name)) + if (!mResultTypes.contains(command)) return false; - type = mResultTypes[name]; + type = mResultTypes[command]; return true; } diff --git a/RedPandaIDE/gdbmiresultparser.h b/RedPandaIDE/gdbmiresultparser.h index 13e0977c..f057ef2a 100644 --- a/RedPandaIDE/gdbmiresultparser.h +++ b/RedPandaIDE/gdbmiresultparser.h @@ -76,7 +76,7 @@ public: public: GDBMIResultParser(); - bool parse(const QByteArray& record, GDBMIResultType& type, ParseValue& value); + bool parse(const QByteArray& record, const QString& command, GDBMIResultType& type, ParseObject& multiValues); bool parseAsyncResult(const QByteArray& record, QByteArray& result, ParseObject& multiValue); private: bool parseMultiValues(const char*p, ParseObject& multiValue); @@ -89,7 +89,7 @@ private: bool isNameChar(char ch); bool isSpaceChar(char ch); private: - QHash mResultTypes; + QHash mResultTypes; }; #endif // GDBMIRESULTPARSER_H diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index bdb1e3a8..51bc48d8 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -1410,9 +1410,6 @@ void MainWindow::debug() updateEditorActions(); return; } - mDebugger->sendCommand("-gdb-set","mi-async on"); - mDebugger->sendCommand("-gdb-set","target-async on"); - mDebugger->sendCommand("-gdb-show", "mi-async"); updateEditorActions(); @@ -4069,7 +4066,7 @@ void MainWindow::onDebugEvaluateInput() if (!s.isEmpty()) { connect(mDebugger, &Debugger::evalValueReady, this, &MainWindow::onEvalValueReady); - mDebugger->sendCommand("print",s); + mDebugger->sendCommand("-data-evaluate-expression",s); } } @@ -4079,7 +4076,7 @@ void MainWindow::onDebugMemoryAddressInput() if (!s.isEmpty()) { connect(mDebugger, &Debugger::memoryExamineReady, this, &MainWindow::onMemoryExamineReady); - mDebugger->sendCommand("-data-read-memory/64bx",s); + mDebugger->sendCommand("-data-read-memory",QString("%1 x 1 8 8 ").arg(s)); } } @@ -5734,7 +5731,6 @@ void MainWindow::on_actionDelete_to_EOL_triggered() } } - void MainWindow::on_actionDelete_to_BOL_triggered() { Editor *e=mEditorList->getEditor(); @@ -5742,12 +5738,3 @@ void MainWindow::on_actionDelete_to_BOL_triggered() e->deleteToBOL(); } } - - -void MainWindow::on_actionPause_triggered() -{ - if (mDebugger->executing()) { - mDebugger->sendCommand("-exec-interrupt","-a"); - } -} - diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index c6ad3f67..39550f94 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -528,8 +528,6 @@ private slots: void on_actionDelete_to_BOL_triggered(); - void on_actionPause_triggered(); - private: Ui::MainWindow *ui; EditorList *mEditorList; diff --git a/RedPandaIDE/mainwindow.ui b/RedPandaIDE/mainwindow.ui index 987029a3..d45c3e17 100644 --- a/RedPandaIDE/mainwindow.ui +++ b/RedPandaIDE/mainwindow.ui @@ -1424,7 +1424,6 @@ - @@ -1643,7 +1642,6 @@ - @@ -2651,18 +2649,6 @@ Ctrl+Backspace - - - - :/icons/images/newlook24/093-pause.png:/icons/images/newlook24/093-pause.png - - - Pause - - - F3 - - diff --git a/RedPandaIDE/widgets/cpudialog.cpp b/RedPandaIDE/widgets/cpudialog.cpp index 75d8ff4d..2e1610ba 100644 --- a/RedPandaIDE/widgets/cpudialog.cpp +++ b/RedPandaIDE/widgets/cpudialog.cpp @@ -87,9 +87,9 @@ void CPUDialog::sendSyntaxCommand() { // Set disassembly flavor if (ui->rdIntel->isChecked()) { - pMainWindow->debugger()->sendCommand("set disassembly-flavor", "intel"); + pMainWindow->debugger()->sendCommand("-gdb-set", "disassembly-flavor intel"); } else { - pMainWindow->debugger()->sendCommand("set disassembly-flavor", "att"); + pMainWindow->debugger()->sendCommand("-gdb-set", "disassembly-flavor att"); } } From 777d11cdcbcbc14362ba26955b96ec21bbbb169e Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Wed, 24 Nov 2021 23:32:34 +0800 Subject: [PATCH 16/32] disassembly finished --- RedPandaIDE/debugger.cpp | 185 ++++++++++++++++++++++++------ RedPandaIDE/debugger.h | 2 + RedPandaIDE/widgets/cpudialog.cpp | 2 +- 3 files changed, 156 insertions(+), 33 deletions(-) diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index 9ce941da..a52dc5f9 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -77,6 +77,8 @@ bool Debugger::start() connect(mReader, &DebugReader::evalUpdated,[this](const QString& value) { emit evalValueReady(value); }); + connect(mReader, &DebugReader::disassemblyUpdate,this, + &Debugger::updateDisassembly); connect(mReader, &DebugReader::inferiorContinued,pMainWindow, &MainWindow::removeActiveBreakpoints); connect(mReader, &DebugReader::inferiorStopped,pMainWindow, @@ -552,6 +554,13 @@ void Debugger::syncFinishedParsing() } } +void Debugger::updateDisassembly(const QStringList &value) +{ + if (pMainWindow->cpuDialog()) { + pMainWindow->cpuDialog()->setDisassembly(value); + } +} + void Debugger::onChangeDebugConsoleLastline(const QString& text) { //pMainWindow->changeDebugOutputLastline(text); @@ -615,7 +624,85 @@ void DebugReader::clearCmdQueue() void DebugReader::processConsoleOutput(const QByteArray& line) { if (line.length()>3 && line.startsWith("~\"") && line.endsWith("\"")) { - mConsoleOutput.append(QString::fromLocal8Bit(line.mid(2,line.length()-3))); + QByteArray s=line.mid(2,line.length()-3); + QByteArray stringValue; + const char *p=s.data(); + while (*p!=0) { + if (*p=='\\' && *(p+1)!=0) { + p++; + switch (*p) { + case '\'': + stringValue+=0x27; + p++; + break; + case '"': + stringValue+=0x22; + p++; + break; + case '?': + stringValue+=0x3f; + p++; + break; + case '\\': + stringValue+=0x5c; + p++; + break; + case 'a': + stringValue+=0x07; + p++; + break; + case 'b': + stringValue+=0x08; + p++; + break; + case 'f': + stringValue+=0x0c; + p++; + break; + case 'n': + stringValue+=0x0a; + p++; + break; + case 'r': + stringValue+=0x0d; + p++; + break; + case 't': + stringValue+=0x09; + p++; + break; + case 'v': + stringValue+=0x0b; + p++; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + { + int i=0; + for (i=0;i<3;i++) { + if (*(p+i)<'0' || *(p+i)>'7') + break; + } + QByteArray numStr(p,i); + bool ok; + unsigned char ch = numStr.toInt(&ok,8); + stringValue+=ch; + p+=i; + break; + } + } + } else { + stringValue+=*p; + p++; + } + } + mConsoleOutput.append(QString::fromLocal8Bit(stringValue)); } } @@ -713,6 +800,7 @@ void DebugReader::processError(const QByteArray &errorLine) void DebugReader::processResultRecord(const QByteArray &line) { + qDebug()<<"process Result:"<=0) { QByteArray result = line.mid(pos+1); processResult(result); + } else if (mCurrentCmd && !(mCurrentCmd->command.startsWith('-'))) { + qDebug()<<"yes"; + qDebug()<command; + if (mCurrentCmd->command == "disas") { + qDebug()<<"yest0"; + QStringList disOutput = mConsoleOutput; + qDebug()<<"yest1"; + if (disOutput.length()>=2) { + qDebug()<<"yest2"; + disOutput.pop_back(); + disOutput.pop_front(); + qDebug()<<"yest4"; + } + qDebug()<<"yest5"; + emit disassemblyUpdate(disOutput); + qDebug()<<"yest6"; + } } return ; } @@ -755,38 +861,45 @@ void DebugReader::processDebugOutput(const QByteArray& debugOutput) mSignalReceived = false; mUpdateCPUInfo = false; mReceivedSFWarning = false; + qDebug()<<"before split"; + QList lines = splitByteArrayToLines(debugOutput); + qDebug()<<"after split"; - QList lines = splitByteArrayToLines(debugOutput); - - for (int i=0;iparams.toLocal8Bit(); } s+= "\n"; + qDebug()<write(s)<0) { emit writeToDebugFailed(); } @@ -1328,10 +1444,15 @@ void DebugReader::run() buffer += readed; if (readed.endsWith("\n")&& outputTerminated(buffer)) { + qDebug()<<"-----"; processDebugOutput(buffer); + qDebug()<<"---1----"; buffer.clear(); + qDebug()<<"---2----"; mCmdRunning = false; + qDebug()<<"---3----"; runNextCmd(); + qDebug()<<"---4----"; } else if (!mCmdRunning && readed.isEmpty()){ runNextCmd(); } else if (readed.isEmpty()){ diff --git a/RedPandaIDE/debugger.h b/RedPandaIDE/debugger.h index 51f8a9a6..17199644 100644 --- a/RedPandaIDE/debugger.h +++ b/RedPandaIDE/debugger.h @@ -241,6 +241,7 @@ private: private slots: void syncFinishedParsing(); + void updateDisassembly(const QStringList& value); void onChangeDebugConsoleLastline(const QString& text); void clearUpReader(); @@ -323,6 +324,7 @@ signals: void localsUpdated(const QStringList& localsValue); void evalUpdated(const QString& value); void memoryUpdated(const QStringList& memoryValues); + void disassemblyUpdate(const QStringList& result); private: void clearCmdQueue(); diff --git a/RedPandaIDE/widgets/cpudialog.cpp b/RedPandaIDE/widgets/cpudialog.cpp index 2e1610ba..577e9fd0 100644 --- a/RedPandaIDE/widgets/cpudialog.cpp +++ b/RedPandaIDE/widgets/cpudialog.cpp @@ -57,7 +57,7 @@ void CPUDialog::updateInfo() if (pMainWindow->debugger()->executing()) { // Load the registers.. sendSyntaxCommand(); - pMainWindow->debugger()->sendCommand("info", "registers"); + //pMainWindow->debugger()->sendCommand("info", "registers"); if (ui->chkBlendMode->isChecked()) pMainWindow->debugger()->sendCommand("disas", "/s"); else From 73c88065f80e360642ed09c83712a47201c3fb53 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Thu, 25 Nov 2021 07:42:56 +0800 Subject: [PATCH 17/32] work save --- RedPandaIDE/debugger.cpp | 60 ++++++++++++------------------- RedPandaIDE/debugger.h | 7 ++-- RedPandaIDE/widgets/cpudialog.cpp | 8 ++--- RedPandaIDE/widgets/cpudialog.h | 3 +- 4 files changed, 32 insertions(+), 46 deletions(-) diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index a52dc5f9..bff1edae 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -71,12 +71,10 @@ bool Debugger::start() &BreakpointModel::updateBreakpointNumber); connect(mReader, &DebugReader::localsUpdated, pMainWindow, &MainWindow::onLocalsReady); - connect(mReader, &DebugReader::memoryUpdated,[this](const QStringList& memory) { - emit memoryExamineReady(memory); - }); - connect(mReader, &DebugReader::evalUpdated,[this](const QString& value) { - emit evalValueReady(value); - }); + connect(mReader, &DebugReader::memoryUpdated,this, + &Debugger::updateMemory); + connect(mReader, &DebugReader::evalUpdated,this, + &Debugger::updateEval); connect(mReader, &DebugReader::disassemblyUpdate,this, &Debugger::updateDisassembly); connect(mReader, &DebugReader::inferiorContinued,pMainWindow, @@ -554,10 +552,20 @@ void Debugger::syncFinishedParsing() } } -void Debugger::updateDisassembly(const QStringList &value) +void Debugger::updateMemory(const QStringList &value) +{ + emit memoryExamineReady(value); +} + +void Debugger::updateEval(const QString &value) +{ + emit evalValueReady(value); +} + +void Debugger::updateDisassembly(const QString& file, const QString& func, const QStringList &value) { if (pMainWindow->cpuDialog()) { - pMainWindow->cpuDialog()->setDisassembly(value); + pMainWindow->cpuDialog()->setDisassembly(file,func,value); } } @@ -752,6 +760,7 @@ void DebugReader::processExecAsyncRecord(const QByteArray &line) mCurrentAddress=0; mCurrentFile.clear(); mCurrentLine=-1; + mCurrentFunc.clear(); emit inferiorContinued(); return; } @@ -781,6 +790,7 @@ void DebugReader::processExecAsyncRecord(const QByteArray &line) mCurrentAddress = frameObj["addr"].hexValue(); mCurrentLine = frameObj["line"].intValue(); mCurrentFile = frameObj["fullname"].pathValue(); + mCurrentFunc = frameObj["func"].value(); } if (reason == "signal-received") { mSignalReceived = true; @@ -800,7 +810,6 @@ void DebugReader::processError(const QByteArray &errorLine) void DebugReader::processResultRecord(const QByteArray &line) { - qDebug()<<"process Result:"<=0) { QByteArray result = line.mid(pos+1); processResult(result); } else if (mCurrentCmd && !(mCurrentCmd->command.startsWith('-'))) { - qDebug()<<"yes"; - qDebug()<command; if (mCurrentCmd->command == "disas") { - qDebug()<<"yest0"; - QStringList disOutput = mConsoleOutput; - qDebug()<<"yest1"; - if (disOutput.length()>=2) { - qDebug()<<"yest2"; + QStringList disOutput = mConsoleOutput; + if (disOutput.length()>=3) { disOutput.pop_back(); disOutput.pop_front(); - qDebug()<<"yest4"; + disOutput.pop_front(); } - qDebug()<<"yest5"; - emit disassemblyUpdate(disOutput); - qDebug()<<"yest6"; + emit disassemblyUpdate(mCurrentFile,mCurrentFunc, disOutput); } } return ; @@ -861,20 +862,15 @@ void DebugReader::processDebugOutput(const QByteArray& debugOutput) mSignalReceived = false; mUpdateCPUInfo = false; mReceivedSFWarning = false; - qDebug()<<"before split"; QList lines = splitByteArrayToLines(debugOutput); - qDebug()<<"after split"; for (int i=0;iparams.toLocal8Bit(); } s+= "\n"; - qDebug()<write(s)<0) { emit writeToDebugFailed(); } @@ -1444,15 +1433,10 @@ void DebugReader::run() buffer += readed; if (readed.endsWith("\n")&& outputTerminated(buffer)) { - qDebug()<<"-----"; processDebugOutput(buffer); - qDebug()<<"---1----"; buffer.clear(); - qDebug()<<"---2----"; mCmdRunning = false; - qDebug()<<"---3----"; runNextCmd(); - qDebug()<<"---4----"; } else if (!mCmdRunning && readed.isEmpty()){ runNextCmd(); } else if (readed.isEmpty()){ diff --git a/RedPandaIDE/debugger.h b/RedPandaIDE/debugger.h index 17199644..abbe6ef9 100644 --- a/RedPandaIDE/debugger.h +++ b/RedPandaIDE/debugger.h @@ -241,7 +241,9 @@ private: private slots: void syncFinishedParsing(); - void updateDisassembly(const QStringList& value); + void updateMemory(const QStringList& value); + void updateEval(const QString& value); + void updateDisassembly(const QString& file, const QString& func,const QStringList& value); void onChangeDebugConsoleLastline(const QString& text); void clearUpReader(); @@ -324,7 +326,7 @@ signals: void localsUpdated(const QStringList& localsValue); void evalUpdated(const QString& value); void memoryUpdated(const QStringList& memoryValues); - void disassemblyUpdate(const QStringList& result); + void disassemblyUpdate(const QString& filename, const QString& funcName, const QStringList& result); private: void clearCmdQueue(); @@ -379,6 +381,7 @@ private: int mCurrentLine; int mCurrentAddress; + QString mCurrentFunc; QString mCurrentFile; QStringList mConsoleOutput; QStringList mFullOutput; diff --git a/RedPandaIDE/widgets/cpudialog.cpp b/RedPandaIDE/widgets/cpudialog.cpp index 577e9fd0..03b81b6b 100644 --- a/RedPandaIDE/widgets/cpudialog.cpp +++ b/RedPandaIDE/widgets/cpudialog.cpp @@ -65,14 +65,12 @@ void CPUDialog::updateInfo() } } -void CPUDialog::setDisassembly(const QStringList &lines) +void CPUDialog::setDisassembly(const QString& file, const QString& funcName,const QStringList& lines) { - if (lines.size()>0) { - ui->txtFunctionName->setText(lines[0]); - } + ui->txtFunctionName->setText(QString("%1:%2").arg(file, funcName)); int activeLine = -1; ui->txtCode->lines()->clear(); - for (int i=1;i")) { activeLine = i; diff --git a/RedPandaIDE/widgets/cpudialog.h b/RedPandaIDE/widgets/cpudialog.h index 870e2af8..6cbcbc17 100644 --- a/RedPandaIDE/widgets/cpudialog.h +++ b/RedPandaIDE/widgets/cpudialog.h @@ -15,7 +15,8 @@ public: explicit CPUDialog(QWidget *parent = nullptr); ~CPUDialog(); void updateInfo(); - void setDisassembly(const QStringList& lines); +public slots: + void setDisassembly(const QString& file, const QString& funcName,const QStringList& lines); signals: void closed(); private: From af1bc5f538c7651730ec8a1ea7cbdc074c60df92 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Thu, 25 Nov 2021 09:05:45 +0800 Subject: [PATCH 18/32] can handle signal --- RedPandaIDE/RedPandaIDE.pro | 9 +- RedPandaIDE/debugger.cpp | 128 +++++++++++++------- RedPandaIDE/debugger.h | 31 ++--- RedPandaIDE/gdbmiresultparser.cpp | 2 + RedPandaIDE/main.cpp | 1 + RedPandaIDE/mainwindow.cpp | 16 ++- RedPandaIDE/mainwindow.h | 1 + RedPandaIDE/widgets/cpudialog.cpp | 4 +- RedPandaIDE/widgets/signalmessagedialog.cpp | 24 ++++ RedPandaIDE/widgets/signalmessagedialog.h | 24 ++++ RedPandaIDE/widgets/signalmessagedialog.ui | 90 ++++++++++++++ 11 files changed, 263 insertions(+), 67 deletions(-) create mode 100644 RedPandaIDE/widgets/signalmessagedialog.cpp create mode 100644 RedPandaIDE/widgets/signalmessagedialog.h create mode 100644 RedPandaIDE/widgets/signalmessagedialog.ui diff --git a/RedPandaIDE/RedPandaIDE.pro b/RedPandaIDE/RedPandaIDE.pro index 0dea66be..05cb6ca8 100644 --- a/RedPandaIDE/RedPandaIDE.pro +++ b/RedPandaIDE/RedPandaIDE.pro @@ -135,7 +135,8 @@ SOURCES += \ widgets/qconsole.cpp \ widgets/qpatchedcombobox.cpp \ widgets/searchdialog.cpp \ - widgets/searchresultview.cpp + widgets/searchresultview.cpp \ + widgets/signalmessagedialog.cpp HEADERS += \ ConvertUTF.h \ @@ -260,7 +261,8 @@ HEADERS += \ widgets/qconsole.h \ widgets/qpatchedcombobox.h \ widgets/searchdialog.h \ - widgets/searchresultview.h + widgets/searchresultview.h \ + widgets/signalmessagedialog.h FORMS += \ settingsdialog/compilerautolinkwidget.ui \ @@ -305,7 +307,8 @@ FORMS += \ widgets/filepropertiesdialog.ui \ widgets/newprojectdialog.ui \ widgets/ojproblempropertywidget.ui \ - widgets/searchdialog.ui + widgets/searchdialog.ui \ + widgets/signalmessagedialog.ui TRANSLATIONS += \ RedPandaIDE_zh_CN.ts diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index bff1edae..5387307b 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -15,6 +15,7 @@ #include #include #include +#include "widgets/signalmessagedialog.h" Debugger::Debugger(QObject *parent) : QObject(parent) { @@ -77,6 +78,10 @@ bool Debugger::start() &Debugger::updateEval); connect(mReader, &DebugReader::disassemblyUpdate,this, &Debugger::updateDisassembly); + connect(mReader, &DebugReader::registerNamesUpdated, this, + &Debugger::updateRegisterNames); + connect(mReader, &DebugReader::registerValuesUpdated, this, + &Debugger::updateRegisterValues); connect(mReader, &DebugReader::inferiorContinued,pMainWindow, &MainWindow::removeActiveBreakpoints); connect(mReader, &DebugReader::inferiorStopped,pMainWindow, @@ -133,6 +138,16 @@ void Debugger::clearUpReader() } } +void Debugger::updateRegisterNames(const QStringList ®isterNames) +{ + mRegisterModel->updateNames(registerNames); +} + +void Debugger::updateRegisterValues(const QHash &values) +{ + mRegisterModel->updateValues(values); +} + RegisterModel *Debugger::registerModel() const { return mRegisterModel; @@ -489,31 +504,16 @@ void Debugger::syncFinishedParsing() return; } - // Some part of the CPU form has been updated - if (pMainWindow->cpuDialog()!=nullptr && !mReader->signalReceived()) { -// if (mReader->doregistersready) { -// mRegisterModel->update(mReader->mRegisters); -// mReader->mRegisters.clear(); -// mReader->doregistersready = false; -// } - -// if (mReader->dodisassemblerready) { -// pMainWindow->cpuDialog()->setDisassembly(mReader->mDisassembly); -// mReader->mDisassembly.clear(); -// mReader->dodisassemblerready = false; -// } - } - -// if (mReader->updateExecution()) { -// if (mReader->currentCmd() && mReader->currentCmd()->source == DebugCommandSource::Console) { -// pMainWindow->setActiveBreakpoint(mReader->breakPointFile(), mReader->breakPointLine(),false); -// } else { -// pMainWindow->setActiveBreakpoint(mReader->breakPointFile(), mReader->breakPointLine()); -// } -// refreshWatchVars(); // update variable information -// } - if (mReader->signalReceived()) { + SignalMessageDialog dialog(pMainWindow); + dialog.setMessage( + tr("Signal \"%1\" Received: ").arg(mReader->signalName()) + + "
" + + mReader->signalMeaning()); + int result = dialog.exec(); + if (result == QDialog::Accepted && dialog.openCPUInfo()) { + pMainWindow->showCPUInfoDialog(); + } //SignalDialog := CreateMessageDialog(fSignal, mtError, [mbOk]); //SignalCheck := TCheckBox.Create(SignalDialog); @@ -595,7 +595,6 @@ DebugReader::DebugReader(Debugger* debugger, QObject *parent) : QThread(parent), { mDebugger = debugger; mProcess = nullptr; - mUseUTF8 = false; mCmdRunning = false; mInvalidateAllVars = false; } @@ -744,6 +743,12 @@ void DebugReader::processResult(const QByteArray &result) case GDBMIResultType::Memory: handleMemory(multiValues["memory"].array()); return; + case GDBMIResultType::RegisterNames: + handleRegisterNames(multiValues["register-names"].array()); + return; + case GDBMIResultType::RegisterValues: + handleRegisterValue(multiValues["register-values"].array()); + return; } } @@ -794,6 +799,8 @@ void DebugReader::processExecAsyncRecord(const QByteArray &line) } if (reason == "signal-received") { mSignalReceived = true; + mSignalName = multiValues["signal-name"].value(); + mSignalMeaning = multiValues["signal-meaning"].value(); } runInferiorStoppedHook(); if (mCurrentCmd && mCurrentCmd->source == DebugCommandSource::Console) @@ -1284,6 +1291,33 @@ void DebugReader::handleMemory(const QList &rows) emit memoryUpdated(memory); } +void DebugReader::handleRegisterNames(const QList &names) +{ + QStringList nameList; + foreach (const GDBMIResultParser::ParseValue& nameValue, names) { + nameList.append(nameValue.value()); + } + emit registerNamesUpdated(nameList); +} + +void DebugReader::handleRegisterValue(const QList &values) +{ + QHash result; + foreach (const GDBMIResultParser::ParseValue& val, values) { + GDBMIResultParser::ParseObject obj = val.object(); + int number = obj["number"].intValue(); + QString value = obj["value"].value(); + bool ok; + long long intVal; + intVal = value.toLongLong(&ok,10); + if (ok) { + value = QString("0x%1").arg(intVal,0,16); + } + result.insert(number,value); + } + emit registerValuesUpdated(result); +} + QByteArray DebugReader::removeToken(const QByteArray &line) { int p=0; @@ -1299,6 +1333,16 @@ QByteArray DebugReader::removeToken(const QByteArray &line) return line; } +const QString &DebugReader::signalMeaning() const +{ + return mSignalMeaning; +} + +const QString &DebugReader::signalName() const +{ + return mSignalName; +} + bool DebugReader::inferiorRunning() const { return mInferiorRunning; @@ -2042,32 +2086,27 @@ RegisterModel::RegisterModel(QObject *parent):QAbstractTableModel(parent) int RegisterModel::rowCount(const QModelIndex &) const { - return mRegisters.count(); + return mRegisterNames.count(); } int RegisterModel::columnCount(const QModelIndex &) const { - return 3; + return 2; } QVariant RegisterModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); - if (index.row()<0 || index.row() >= static_cast(mRegisters.size())) - return QVariant(); - PRegister reg = mRegisters[index.row()]; - if (!reg) + if (index.row()<0 || index.row() >= static_cast(mRegisterNames.size())) return QVariant(); switch (role) { case Qt::DisplayRole: switch (index.column()) { case 0: - return reg->name; + return mRegisterNames[index.row()]; case 1: - return reg->hexValue; - case 2: - return reg->decValue; + return mRegisterValues.value(index.row(),""); default: return QVariant(); } @@ -2083,26 +2122,31 @@ QVariant RegisterModel::headerData(int section, Qt::Orientation orientation, int case 0: return tr("Register"); case 1: - return tr("Value(Hex)"); - case 2: - return tr("Value(Dec)"); + return tr("Value"); } } return QVariant(); } -void RegisterModel::update(const QList ®s) +void RegisterModel::updateNames(const QStringList ®Names) { beginResetModel(); - mRegisters.clear(); - mRegisters.append(regs); + mRegisterNames = regNames; endResetModel(); } +void RegisterModel::updateValues(const QHash registerValues) +{ + mRegisterValues= registerValues; + emit dataChanged(createIndex(0,1), + createIndex(mRegisterNames.count()-1,1)); +} + void RegisterModel::clear() { beginResetModel(); - mRegisters.clear(); + mRegisterNames.clear(); + mRegisterValues.clear(); endResetModel(); } diff --git a/RedPandaIDE/debugger.h b/RedPandaIDE/debugger.h index abbe6ef9..40ec39c2 100644 --- a/RedPandaIDE/debugger.h +++ b/RedPandaIDE/debugger.h @@ -60,14 +60,6 @@ struct Trace { using PTrace = std::shared_ptr; -struct Register { - QString name; - QString hexValue; - QString decValue; -}; - -using PRegister = std::shared_ptr; - class RegisterModel: public QAbstractTableModel { Q_OBJECT public: @@ -76,10 +68,12 @@ public: int columnCount(const QModelIndex &parent) const override; QVariant data(const QModelIndex &index, int role) const override; QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - void update(const QList& regs); + void updateNames(const QStringList& regNames); + void updateValues(const QHash registerValues); void clear(); private: - QList mRegisters; + QStringList mRegisterNames; + QHash mRegisterValues; }; class BreakpointModel: public QAbstractTableModel { @@ -246,6 +240,8 @@ private slots: void updateDisassembly(const QString& file, const QString& func,const QStringList& value); void onChangeDebugConsoleLastline(const QString& text); void clearUpReader(); + void updateRegisterNames(const QStringList& registerNames); + void updateRegisterValues(const QHash& values); private: bool mExecuting; @@ -310,6 +306,10 @@ public: bool inferiorRunning() const; + const QString &signalName() const; + + const QString &signalMeaning() const; + signals: void parseStarted(); void invalidateAllVars(); @@ -327,6 +327,8 @@ signals: void evalUpdated(const QString& value); void memoryUpdated(const QStringList& memoryValues); void disassemblyUpdate(const QString& filename, const QString& funcName, const QStringList& result); + void registerNamesUpdated(const QStringList& registerNames); + void registerValuesUpdated(const QHash& values); private: void clearCmdQueue(); @@ -341,6 +343,8 @@ private: void handleLocalVariables(const QList & variables); void handleEvaluation(const QString& value); void handleMemory(const QList & rows); + void handleRegisterNames(const QList & names); + void handleRegisterValue(const QList & values); void processConsoleOutput(const QByteArray& line); void processResult(const QByteArray& result); void processExecAsyncRecord(const QByteArray& line); @@ -360,15 +364,12 @@ private: //fOnInvalidateAllVars: TInvalidateAllVarsEvent; bool mCmdRunning; PDebugCommand mCurrentCmd; - QList mRegisters; - QStringList mDisassembly; - QProcess* mProcess; //fWatchView: TTreeView; - QString mSignal; - bool mUseUTF8; + QString mSignalName; + QString mSignalMeaning; // QList mInferiorStoppedHookCommands; diff --git a/RedPandaIDE/gdbmiresultparser.cpp b/RedPandaIDE/gdbmiresultparser.cpp index 0ebc5157..961da48a 100644 --- a/RedPandaIDE/gdbmiresultparser.cpp +++ b/RedPandaIDE/gdbmiresultparser.cpp @@ -16,6 +16,8 @@ GDBMIResultParser::GDBMIResultParser() // mResultTypes.insert("register-names",GDBMIResultType::RegisterNames); // mResultTypes.insert("register-values",GDBMIResultType::RegisterValues); mResultTypes.insert("-data-read-memory",GDBMIResultType::Memory); + mResultTypes.insert("-data-list-register-names",GDBMIResultType::RegisterNames); + mResultTypes.insert("-data-list-register-values",GDBMIResultType::RegisterValues); } bool GDBMIResultParser::parse(const QByteArray &record, const QString& command, GDBMIResultType &type, ParseObject& multiValues) diff --git a/RedPandaIDE/main.cpp b/RedPandaIDE/main.cpp index c3709e8a..64d8fd45 100644 --- a/RedPandaIDE/main.cpp +++ b/RedPandaIDE/main.cpp @@ -103,6 +103,7 @@ int main(int argc, char *argv[]) qRegisterMetaType("PCompileIssue"); qRegisterMetaType("PCompileIssue&"); qRegisterMetaType>("QVector"); + qRegisterMetaType>("QHash"); initParser(); diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 51bc48d8..69090b43 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -1432,6 +1432,7 @@ void MainWindow::debug() mDebugger->sendAllBreakpointsToDebugger(); // Run the debugger + mDebugger->sendCommand("-data-list-register-names",""); mDebugger->sendCommand("-gdb-set", "width 0"); // don't wrap output, very annoying mDebugger->sendCommand("-gdb-set", "new-console on"); mDebugger->sendCommand("-gdb-set", "confirm off"); @@ -1474,6 +1475,15 @@ void MainWindow::showSearchPanel(bool showReplace) ui->tabMessages->setCurrentWidget(ui->tabSearch); } +void MainWindow::showCPUInfoDialog() +{ + if (mCPUDialog==nullptr) { + mCPUDialog = new CPUDialog(this); + connect(mCPUDialog, &CPUDialog::closed, this, &MainWindow::cleanUpCPUDialog); + } + mCPUDialog->show(); +} + void MainWindow::openCloseBottomPanel(bool open) { // if Assigned(fReportToolWindow) then @@ -4048,11 +4058,7 @@ void MainWindow::on_actionAdd_Watch_triggered() void MainWindow::on_actionView_CPU_Window_triggered() { - if (mCPUDialog==nullptr) { - mCPUDialog = new CPUDialog(this); - connect(mCPUDialog, &CPUDialog::closed, this, &MainWindow::cleanUpCPUDialog); - } - mCPUDialog->show(); + showCPUInfoDialog(); } void MainWindow::on_actionExit_triggered() diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index 39550f94..8e647ca4 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -95,6 +95,7 @@ public: void runExecutable(RunType runType = RunType::Normal); void debug(); void showSearchPanel(bool showReplace = false); + void showCPUInfoDialog(); void applySettings(); void applyUISettings(); diff --git a/RedPandaIDE/widgets/cpudialog.cpp b/RedPandaIDE/widgets/cpudialog.cpp index 03b81b6b..8494e430 100644 --- a/RedPandaIDE/widgets/cpudialog.cpp +++ b/RedPandaIDE/widgets/cpudialog.cpp @@ -57,7 +57,7 @@ void CPUDialog::updateInfo() if (pMainWindow->debugger()->executing()) { // Load the registers.. sendSyntaxCommand(); - //pMainWindow->debugger()->sendCommand("info", "registers"); + pMainWindow->debugger()->sendCommand("-data-list-register-values", "N"); if (ui->chkBlendMode->isChecked()) pMainWindow->debugger()->sendCommand("disas", "/s"); else @@ -78,7 +78,7 @@ void CPUDialog::setDisassembly(const QString& file, const QString& funcName,cons ui->txtCode->lines()->add(line); } if (activeLine!=-1) - ui->txtCode->setCaretXY(BufferCoord{1,activeLine}); + ui->txtCode->setCaretXYCentered(true,BufferCoord{1,activeLine}); } void CPUDialog::sendSyntaxCommand() diff --git a/RedPandaIDE/widgets/signalmessagedialog.cpp b/RedPandaIDE/widgets/signalmessagedialog.cpp new file mode 100644 index 00000000..b44e5730 --- /dev/null +++ b/RedPandaIDE/widgets/signalmessagedialog.cpp @@ -0,0 +1,24 @@ +#include "signalmessagedialog.h" +#include "ui_signalmessagedialog.h" + +SignalMessageDialog::SignalMessageDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::SignalMessageDialog) +{ + ui->setupUi(this); +} + +SignalMessageDialog::~SignalMessageDialog() +{ + delete ui; +} + +void SignalMessageDialog::setMessage(const QString &message) +{ + ui->lblMessage->setText(message); +} + +bool SignalMessageDialog::openCPUInfo() +{ + return ui->chkOpenCPUInfo->isChecked(); +} diff --git a/RedPandaIDE/widgets/signalmessagedialog.h b/RedPandaIDE/widgets/signalmessagedialog.h new file mode 100644 index 00000000..f7781fcf --- /dev/null +++ b/RedPandaIDE/widgets/signalmessagedialog.h @@ -0,0 +1,24 @@ +#ifndef SIGNALMESSAGEDIALOG_H +#define SIGNALMESSAGEDIALOG_H + +#include + +namespace Ui { +class SignalMessageDialog; +} + +class SignalMessageDialog : public QDialog +{ + Q_OBJECT + +public: + explicit SignalMessageDialog(QWidget *parent = nullptr); + ~SignalMessageDialog(); + void setMessage(const QString& message); + bool openCPUInfo(); + +private: + Ui::SignalMessageDialog *ui; +}; + +#endif // SIGNALMESSAGEDIALOG_H diff --git a/RedPandaIDE/widgets/signalmessagedialog.ui b/RedPandaIDE/widgets/signalmessagedialog.ui new file mode 100644 index 00000000..4c6deff6 --- /dev/null +++ b/RedPandaIDE/widgets/signalmessagedialog.ui @@ -0,0 +1,90 @@ + + + SignalMessageDialog + + + + 0 + 0 + 400 + 240 + + + + Signal Received + + + + + + + 0 + 0 + + + + TextLabel + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + Open CPU Info Dialog + + + true + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + SignalMessageDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + SignalMessageDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + From adf001124c253cc167e2088e7401c277972281aa Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Thu, 25 Nov 2021 09:07:29 +0800 Subject: [PATCH 19/32] update translations --- RedPandaIDE/RedPandaIDE_zh_CN.qm | Bin 106597 -> 106747 bytes RedPandaIDE/RedPandaIDE_zh_CN.ts | 402 ++++++++++++++++--------------- 2 files changed, 212 insertions(+), 190 deletions(-) diff --git a/RedPandaIDE/RedPandaIDE_zh_CN.qm b/RedPandaIDE/RedPandaIDE_zh_CN.qm index 398781d0ae69e8e4f7bdd74763b6bdb35ac0c033..89b09bfb16bc10e9c0402bd7b70575c2042dffef 100644 GIT binary patch delta 10144 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 BacktraceModel - + Function 函数 - + Filename 文件名 - + Line @@ -151,37 +151,37 @@ BreakpointModel - + Filename 文件名 - + Line - + Condition 条件 - + Save file '%1' failed. 保存文件'%1'失败。 - + Can't open file '%1' for write. 无法写入文件'%1'. - + Error in json file '%1':%2 : %3 JSON文件'%1':%2中存在错误:%3 - + Can't open file '%1' for read. 无法读取文件'%1'. @@ -947,71 +947,76 @@ Are you really want to continue? Debugger - + No compiler set 无编译器设置 - + No compiler set is configured. 没有配置编译器设置。 - + Can't start debugging. 无法启动调试器 - + Debugger path error 调试路径错误 - + Debugger's path "%1" contains non-ascii characters. 调试路径"%1"中包含非ASCII字符(如,中文字符) - + This prevents it from executing. 这会导致调试器无法启动。 - + Debugger not exists 找不到调试器 - + Can''t find debugger in : "%1" 找不到调试器程序"%1" - - + + Execute to evaluate 执行以求值 - + Not found in current context 不在当前语境中 - + Compile 编译 - + Source file is more recent than executable. 源文件比程序文件新。 - + Recompile? 重新编译? + + + Signal "%1" Received: + 收到信号"%1": + Editor @@ -2857,11 +2862,11 @@ Are you really want to continue? - - + - + + Issues 编译器 @@ -3117,8 +3122,8 @@ Are you really want to continue? - - + + Copy 复制 @@ -3129,7 +3134,7 @@ Are you really want to continue? - + Paste 粘贴 @@ -3140,7 +3145,7 @@ Are you really want to continue? - + Select All 选择全部 @@ -3267,7 +3272,7 @@ Are you really want to continue? - + New Problem Set 新建试题集 @@ -3286,14 +3291,14 @@ Are you really want to continue? - + Save Problem Set 保存试题集 - + Load Problem Set 载入试题集 @@ -3628,7 +3633,7 @@ Are you really want to continue? - + Clear all breakpoints 删除所有断点 @@ -3729,7 +3734,7 @@ Are you really want to continue? - + Rename Symbol 重命名符号 @@ -3750,13 +3755,13 @@ Are you really want to continue? - + Export As RTF 导出为RTF - + Export As HTML 导出为HTML @@ -3876,7 +3881,7 @@ Are you really want to continue? - + Open Folder 打开文件夹 @@ -3886,7 +3891,7 @@ Are you really want to continue? 运行参数... - + File Encoding 文件编码 @@ -4059,39 +4064,39 @@ Are you really want to continue? 重新编译? - - + + Save last open info error 保存上次打开信息失败 - + Can't remove old last open information file '%1' 无法删除旧上次打开信息文件'%1' - + Can't save last open info file '%1' 无法保存上次打开信息文件'%1' - + Load last open info error 载入上次打开信息失败 - + Can't load last open info file '%1' 无法载入上次打开信息文件'%1' - + Copy all 全部复制 - - + + Clear 清除 @@ -4107,7 +4112,7 @@ Are you really want to continue? - + Problem Set %1 试题集%1 @@ -4134,6 +4139,7 @@ Are you really want to continue? + Rebuild Project 重新构建项目 @@ -4144,427 +4150,422 @@ Are you really want to continue? 项目已经被修改过,是否需要重新构建? - - Compile Project - 编译项目 - - - + Auto Save Error 自动保存出错 - + Auto save "%1" to "%2" failed:%3 自动保存"%1"到"%2"失败:%3 - + Properties... 试题属性... - + Set Problem Set Name 设置试题集名称 - + Problem Set Name: 试题集名称: - + Remove 删除 - + Remove All Bookmarks 删除全部书签 - + Modify Description 修改描述 - - - + + + Bookmark Description 书签描述 - - - + + + Description: 描述: - + Show debug logs in the debug console 在调试主控台中显示调试器输出 - + Remove this search 清除这次搜索 - + Clear all searches 删除所有搜索 - + Breakpoint condition... 断点条件... - + Break point condition 断点条件 - + Enter the condition of the breakpoint: 输入当前断点的生效条件: - + Remove All Breakpoints Remove all breakpoints 删除所有断点 - + Remove Breakpoint 删除当前断点 - + Rename File 重命名文件 - - + + Add Folder 添加文件夹 - + New folder 新文件夹 - + Folder name: 文件夹: - + Rename Folder 重命名 - + Remove Folder 删除文件夹 - + Sort By Type 按类型排序 - + Sort alphabetically 按名称排序 - + Show inherited members 显示继承的成员 - + Goto declaration 跳转到声明处 - + Goto definition 跳转到定义处 - + Open in Editor 在编辑器中打开 - + Open in External Program 使用外部程序打开 - + Open in Terminal 在终端中打开 - + Open in Windows Explorer 在Windows浏览器中打开 - + Character sets 字符集 - + %1 files autosaved 已自动保存%1个文件 - + Set answer to... 设置答案源代码... - + select other file... 选择其他文件... - + Select Answer Source File 选择答案源代码文件 - + C/C++Source Files (*.c *.cpp *.cc *.cxx) C/C++Source Files (*.c *.cpp *.cc *.cxx C/C++源代码文件 (*.c *.cpp *.cc *.cxx) - + Save project 保存项目 - + The project '%1' has modifications. 项目'%1'有改动。 - - + + Do you want to save it? 需要保存吗? - - + + File Changed 文件已发生变化 - + New Project File? 新建项目文件? - + Do you want to add the new file to the project? 您是否要将新建的文件加入项目? - - - - + + + + Save Error 保存失败 - + Change Project Compiler Set 改变项目编译器配置集 - + Change the project's compiler set will lose all custom compiler set options. 改变项目的编译器配置集会导致所有的自定义编译器选项被重置。 - + Do you really want to do that? 你真的想要做那些吗? - + Do you really want to clear all breakpoints in this file? 您真的要清除该文件的所有断点吗? - + New project 新建项目 - + Close %1 and start new project? 关闭'%1'以打开新项目? - + Folder not exist 文件夹不存在 - + Folder '%1' doesn't exist. Create it now? 文件夹'%1'不存在。是否创建? - + Can't create folder 无法创建文件夹 - + Failed to create folder '%1'. 创建文件夹'%1'失败。 - + Save new project as - + Red panda Dev-C++ project file (*.dev) 小熊猫Dev-C++项目文件 (*.dev) - + New project fail 新建项目失败 - + Can't assign project template 无法使用模板创建项目 - + Remove file 删除文件 - + Remove the file from disk? 同时从硬盘上删除文件? - + untitled 无标题 - + New Project File Name 新的项目文件名 - + File Name: 文件名: - + File Already Exists! 文件已存在! - + File '%1' already exists! 文件'%1'已经存在! - + Add to project 添加到项目 - + Rename Error 重命名出错 - + Symbol '%1' is defined in system header. 符号'%1'在系统头文件中定义,无法修改。 - + New Name 新名称 + - Replace Error 替换出错 - + Can't open file '%1' for replace! 无法打开文件'%1'进行替换! - + Contents has changed since last search! 内容和上次查找时不一致。 - + Rich Text Format Files (*.rtf) RTF格式文件 (*.rtf) - + HTML Files (*.html) HTML文件 (*.html) - + The current problem set is not empty. 当前的试题集不是空的。 - + Problem %1 试题%1 - - + + Problem Set Files (*.pbs) 试题集文件 (*.pbs) - + Load Error 载入失败 - - + + Problem Case %1 试题案例%1 @@ -4576,14 +4577,14 @@ Are you really want to continue? - - - - - - - - + + + + + + + + Error 错误 @@ -4593,75 +4594,75 @@ Are you really want to continue? 项目历史 - + File '%1' was changed. 磁盘文件'%1'已被修改。 - + Reload its content from disk? 是否重新读取它的内容? - + File '%1' was removed. 磁盘文件'%1'已被删除。 - + Keep it open? 是否保持它在小熊猫C++中打开的编辑窗口? - + Open 打开 - + Compile Failed 编译失败 - + Run Failed 运行失败 - - + + Confirm Convertion 确认转换 - - + + The editing file will be saved using %1 encoding. <br />This operation can't be reverted. <br />Are you sure to continue? 当前编辑器中的文件将会使用%1编码保存。<br />这项操作无法被撤回。<br />你确定要继续吗? - + New Watch Expression 新监视表达式 - + Enter Watch Expression (it is recommended to use 'this->' for class members): 输入监视表达式 - + Parsing file %1 of %2: "%3" (%1/%2)正在解析文件"%3" - - + + Done parsing %1 files in %2 seconds 完成%1个文件的解析,用时%2秒 - + (%1 files per second) (每秒%1个文件) @@ -5495,7 +5496,7 @@ Are you really want to continue? QApplication - + Error 错误 @@ -5565,7 +5566,7 @@ Are you really want to continue? 无法写入配置文件夹"%1" - + Can't load autolink settings 无法载入自动链接设置 @@ -6177,19 +6178,22 @@ Are you really want to continue? RegisterModel - + Register 寄存器 - - Value(Hex) - 值(HEX) + + Value + + + + Value(Hex) + 值(HEX) - Value(Dec) - 值(DEC) + 值(DEC) @@ -6586,7 +6590,7 @@ Are you really want to continue? 自动链接 - + @@ -6662,7 +6666,7 @@ Are you really want to continue? 杂项 - + Program Runner @@ -6806,6 +6810,24 @@ Are you really want to continue? 写入快捷键配置文件失败'%1'。 + + SignalMessageDialog + + + Signal Received + 收到信号 + + + + TextLabel + + + + + Open CPU Info Dialog + 打开CPU信息窗口 + + StdinCompiler @@ -7057,37 +7079,37 @@ Are you really want to continue? WatchModel - + Save file '%1' failed. 保存文件'%1'失败。 - + Can't open file '%1' for write. 无法写入文件'%1'. - + Error in json file '%1':%2 : %3 JSON文件'%1':%2中存在错误:%3 - + Execute to evaluate 执行以求值 - + Can't open file '%1' for read. 无法读取文件'%1'. - + Expression 表达式 - + Value From 3abbf662514cd4c37beedc8c443db918ae4918ec Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Thu, 25 Nov 2021 10:18:21 +0800 Subject: [PATCH 20/32] add "open cpu window when signaled" debug option --- RedPandaIDE/RedPandaIDE_zh_CN.qm | Bin 106747 -> 106714 bytes RedPandaIDE/RedPandaIDE_zh_CN.ts | 530 +++++++++--------- RedPandaIDE/debugger.cpp | 20 +- RedPandaIDE/debugger.h | 4 - RedPandaIDE/mainwindow.cpp | 51 +- RedPandaIDE/mainwindow.h | 2 +- RedPandaIDE/mainwindow.ui | 2 +- RedPandaIDE/settings.cpp | 36 +- RedPandaIDE/settings.h | 16 +- .../settingsdialog/debuggeneralwidget.cpp | 10 +- .../settingsdialog/debuggeneralwidget.ui | 22 +- RedPandaIDE/widgets/signalmessagedialog.cpp | 5 + RedPandaIDE/widgets/signalmessagedialog.h | 1 + 13 files changed, 365 insertions(+), 334 deletions(-) diff --git a/RedPandaIDE/RedPandaIDE_zh_CN.qm b/RedPandaIDE/RedPandaIDE_zh_CN.qm index 89b09bfb16bc10e9c0402bd7b70575c2042dffef..751c4090e99fd5c582d14f73c906fa6c473fcb3b 100644 GIT binary patch delta 10121 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 TFk*a+adnybQ8P<+VbT8q= BacktraceModel - + Function 函数 - + Filename 文件名 - + Line @@ -151,37 +151,37 @@ BreakpointModel - + Filename 文件名 - + Line - + Condition 条件 - + Save file '%1' failed. 保存文件'%1'失败。 - + Can't open file '%1' for write. 无法写入文件'%1'. - + Error in json file '%1':%2 : %3 JSON文件'%1':%2中存在错误:%3 - + Can't open file '%1' for read. 无法读取文件'%1'. @@ -891,26 +891,31 @@ Are you really want to continue? - Show debug logs in the debug console - 在调试主控台中显示调试器输出 + Show detail debug logs + Show debug logs in the debug console + 显示详细调试器日志 + + + + Show CPU Window when signal received + 程序收到信号停止时缺省打开CPU窗口 - Show full gdb annotations - 在调试主控台中显示gdb输出注解 + 在调试主控台中显示gdb输出注解 - + Autosave 自动保存 - + Autosave breakpoints 自动保存断点 - + Autosave watches 自动保存监视 @@ -947,73 +952,73 @@ Are you really want to continue? Debugger - + No compiler set 无编译器设置 - + No compiler set is configured. 没有配置编译器设置。 - + Can't start debugging. 无法启动调试器 - + Debugger path error 调试路径错误 - + Debugger's path "%1" contains non-ascii characters. 调试路径"%1"中包含非ASCII字符(如,中文字符) - + This prevents it from executing. 这会导致调试器无法启动。 - + Debugger not exists 找不到调试器 - + Can''t find debugger in : "%1" 找不到调试器程序"%1" - - + + Execute to evaluate 执行以求值 - + Not found in current context 不在当前语境中 - + Compile 编译 - + Source file is more recent than executable. 源文件比程序文件新。 - + Recompile? 重新编译? - + Signal "%1" Received: 收到信号"%1": @@ -2862,11 +2867,11 @@ Are you really want to continue? - - - - - + + + + + Issues 编译器 @@ -2942,6 +2947,7 @@ Are you really want to continue? + Debug Console 调试主控台 @@ -3017,7 +3023,7 @@ Are you really want to continue? 工具栏2 - + New 新建 @@ -3075,8 +3081,8 @@ Are you really want to continue? - - + + Compile 编译 @@ -3122,8 +3128,8 @@ Are you really want to continue? - - + + Copy 复制 @@ -3134,7 +3140,7 @@ Are you really want to continue? - + Paste 粘贴 @@ -3145,7 +3151,7 @@ Are you really want to continue? - + Select All 选择全部 @@ -3265,14 +3271,14 @@ Are you really want to continue? - + Problem Set 试题集 - + New Problem Set 新建试题集 @@ -3291,14 +3297,14 @@ Are you really want to continue? - + Save Problem Set 保存试题集 - + Load Problem Set 载入试题集 @@ -3334,7 +3340,7 @@ Are you really want to continue? - + Problem 试题 @@ -3633,7 +3639,7 @@ Are you really want to continue? - + Clear all breakpoints 删除所有断点 @@ -3734,7 +3740,7 @@ Are you really want to continue? - + Rename Symbol 重命名符号 @@ -3755,13 +3761,13 @@ Are you really want to continue? - + Export As RTF 导出为RTF - + Export As HTML 导出为HTML @@ -3881,7 +3887,7 @@ Are you really want to continue? - + Open Folder 打开文件夹 @@ -3891,42 +3897,42 @@ Are you really want to continue? 运行参数... - + File Encoding 文件编码 - + Recent Files 文件历史 - - - - - - + + + + + + Debugging 正在调试 - - - - - - + + + + + + Running 正在运行 - - - - - - + + + + + + Compiling 正在编译 @@ -3935,184 +3941,189 @@ Are you really want to continue? 行:%1 列:%2 已选择:%3 总行数:%4 总长度:%5 - + Line:%1 Col:%2 Selected:%3 Lines:%4 Length:%5 Line: %1 Col: %2 Selected: %3 Lines: %4 Length: %5 行: %1 列: %2 已选择 :%3 总行数: %4 总长度: %5 - + Read Only 只读 - + Insert 插入 - + Overwrite 覆写 - + Close project 关闭项目 - + Are you sure you want to close %1? 你确定要关闭'%1'吗? - - + + Confirm 确认 - - - + + + Source file is not compiled. 源文件尚未编译。 - - + + Compile now? 现在编译? - - - + + + Source file is more recent than executable. 源文件比可执行程序新。 - + Recompile now? 重新编译? - + No compiler set 无编译器设置 - + No compiler set is configured. 没有配置编译器设置。 - + Can't start debugging. 无法启动调试器 - - + + Enable debugging 启用调试参数 - - + + You have not enabled debugging info (-g3) and/or stripped it from the executable (-s) in Compiler Options.<BR /><BR />Do you want to correct this now? 当前编译设置中未启用调试选项(-g3),或启用了信息剥除选项(-s)<br /><br/>是否纠正这一问题? - + Project not built 项目尚未构建 - + Project hasn't been built. Build it now? 项目尚未构建。是否构建? - + Host applcation missing 宿主程序不存在 - + DLL project needs a host application to run. 动态链接库(DLL)需要一个宿主程序来运行。 - + But it's missing. 但它不存在。 - + Host application not exists 宿主程序不存在 - + Host application file '%1' doesn't exist. 宿主程序'%1'不存在。 - + Recompile? 重新编译? - - + + Save last open info error 保存上次打开信息失败 - + Can't remove old last open information file '%1' 无法删除旧上次打开信息文件'%1' - + Can't save last open info file '%1' 无法保存上次打开信息文件'%1' - + Load last open info error 载入上次打开信息失败 - + Can't load last open info file '%1' 无法载入上次打开信息文件'%1' - + + Show detail debug logs + 显示详细调试器日志 + + + Copy all 全部复制 - - + + Clear 清除 - + Export 导出 - + Insert Snippet 插入代码段 - - + + Problem Set %1 试题集%1 @@ -4133,536 +4144,535 @@ Are you really want to continue? 或者选择使用其他的网络端口。 - + Red Panda Dev-C++ 小熊猫Dev-C++ - - + + Rebuild Project 重新构建项目 - - + + Project has been modified, do you want to rebuild it? 项目已经被修改过,是否需要重新构建? - + Auto Save Error 自动保存出错 - + Auto save "%1" to "%2" failed:%3 自动保存"%1"到"%2"失败:%3 - + Properties... 试题属性... - + Set Problem Set Name 设置试题集名称 - + Problem Set Name: 试题集名称: - + Remove 删除 - + Remove All Bookmarks 删除全部书签 - + Modify Description 修改描述 - - - + + + Bookmark Description 书签描述 - - - + + + Description: 描述: - Show debug logs in the debug console - 在调试主控台中显示调试器输出 + 在调试主控台中显示调试器输出 - + Remove this search 清除这次搜索 - + Clear all searches 删除所有搜索 - + Breakpoint condition... 断点条件... - + Break point condition 断点条件 - + Enter the condition of the breakpoint: 输入当前断点的生效条件: - + Remove All Breakpoints Remove all breakpoints 删除所有断点 - + Remove Breakpoint 删除当前断点 - + Rename File 重命名文件 - + Add Folder 添加文件夹 - + New folder 新文件夹 - + Folder name: 文件夹: - + Rename Folder 重命名 - + Remove Folder 删除文件夹 - + Sort By Type 按类型排序 - + Sort alphabetically 按名称排序 - + Show inherited members 显示继承的成员 - + Goto declaration 跳转到声明处 - + Goto definition 跳转到定义处 - + Open in Editor 在编辑器中打开 - + Open in External Program 使用外部程序打开 - + Open in Terminal 在终端中打开 - + Open in Windows Explorer 在Windows浏览器中打开 - + Character sets 字符集 - + %1 files autosaved 已自动保存%1个文件 - + Set answer to... 设置答案源代码... - + select other file... 选择其他文件... - + Select Answer Source File 选择答案源代码文件 - + C/C++Source Files (*.c *.cpp *.cc *.cxx) C/C++Source Files (*.c *.cpp *.cc *.cxx C/C++源代码文件 (*.c *.cpp *.cc *.cxx) - + Save project 保存项目 - + The project '%1' has modifications. 项目'%1'有改动。 - - + + Do you want to save it? 需要保存吗? - - + + File Changed 文件已发生变化 - + New Project File? 新建项目文件? - + Do you want to add the new file to the project? 您是否要将新建的文件加入项目? - - - - + + + + Save Error 保存失败 - + Change Project Compiler Set 改变项目编译器配置集 - + Change the project's compiler set will lose all custom compiler set options. 改变项目的编译器配置集会导致所有的自定义编译器选项被重置。 - + Do you really want to do that? 你真的想要做那些吗? - + Do you really want to clear all breakpoints in this file? 您真的要清除该文件的所有断点吗? - + New project 新建项目 - + Close %1 and start new project? 关闭'%1'以打开新项目? - + Folder not exist 文件夹不存在 - + Folder '%1' doesn't exist. Create it now? 文件夹'%1'不存在。是否创建? - + Can't create folder 无法创建文件夹 - + Failed to create folder '%1'. 创建文件夹'%1'失败。 - + Save new project as - + Red panda Dev-C++ project file (*.dev) 小熊猫Dev-C++项目文件 (*.dev) - + New project fail 新建项目失败 - + Can't assign project template 无法使用模板创建项目 - + Remove file 删除文件 - + Remove the file from disk? 同时从硬盘上删除文件? - + untitled 无标题 - + New Project File Name 新的项目文件名 - + File Name: 文件名: - + File Already Exists! 文件已存在! - + File '%1' already exists! 文件'%1'已经存在! - + Add to project 添加到项目 - + Rename Error 重命名出错 - + Symbol '%1' is defined in system header. 符号'%1'在系统头文件中定义,无法修改。 - + New Name 新名称 - - + + Replace Error 替换出错 - + Can't open file '%1' for replace! 无法打开文件'%1'进行替换! - + Contents has changed since last search! 内容和上次查找时不一致。 - + Rich Text Format Files (*.rtf) RTF格式文件 (*.rtf) - + HTML Files (*.html) HTML文件 (*.html) - + The current problem set is not empty. 当前的试题集不是空的。 - + Problem %1 试题%1 - - + + Problem Set Files (*.pbs) 试题集文件 (*.pbs) - + Load Error 载入失败 - - + + Problem Case %1 试题案例%1 - - - + + - - - - - - - - - - + + + + + + + + + + + Error 错误 - + Recent Projects 项目历史 - + File '%1' was changed. 磁盘文件'%1'已被修改。 - + Reload its content from disk? 是否重新读取它的内容? - + File '%1' was removed. 磁盘文件'%1'已被删除。 - + Keep it open? 是否保持它在小熊猫C++中打开的编辑窗口? - + Open 打开 - + Compile Failed 编译失败 - + Run Failed 运行失败 - - + + Confirm Convertion 确认转换 - - + + The editing file will be saved using %1 encoding. <br />This operation can't be reverted. <br />Are you sure to continue? 当前编辑器中的文件将会使用%1编码保存。<br />这项操作无法被撤回。<br />你确定要继续吗? - + New Watch Expression 新监视表达式 - + Enter Watch Expression (it is recommended to use 'this->' for class members): 输入监视表达式 - + Parsing file %1 of %2: "%3" (%1/%2)正在解析文件"%3" - - + + Done parsing %1 files in %2 seconds 完成%1个文件的解析,用时%2秒 - + (%1 files per second) (每秒%1个文件) @@ -6178,12 +6188,12 @@ Are you really want to continue? RegisterModel - + Register 寄存器 - + Value @@ -6590,7 +6600,7 @@ Are you really want to continue? 自动链接 - + @@ -6666,7 +6676,7 @@ Are you really want to continue? 杂项 - + Program Runner @@ -7079,37 +7089,37 @@ Are you really want to continue? WatchModel - + Save file '%1' failed. 保存文件'%1'失败。 - + Can't open file '%1' for write. 无法写入文件'%1'. - + Error in json file '%1':%2 : %3 JSON文件'%1':%2中存在错误:%3 - + Execute to evaluate 执行以求值 - + Can't open file '%1' for read. 无法读取文件'%1'. - + Expression 表达式 - + Value diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index 5387307b..d6c1ab53 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -24,7 +24,6 @@ Debugger::Debugger(QObject *parent) : QObject(parent) mWatchModel = new WatchModel(this); mRegisterModel = new RegisterModel(this); mExecuting = false; - mUseUTF8 = false; mReader = nullptr; mCommandChanged = false; mLeftPageIndexBackup = -1; @@ -401,16 +400,6 @@ void Debugger::notifyAfterProcessWatchVar() mWatchModel->endUpdate(); } -bool Debugger::useUTF8() const -{ - return mUseUTF8; -} - -void Debugger::setUseUTF8(bool useUTF8) -{ - mUseUTF8 = useUTF8; -} - BacktraceModel* Debugger::backtraceModel() { return mBacktraceModel; @@ -486,8 +475,8 @@ void Debugger::syncFinishedParsing() // show command output - if (pSettings->debugger().showCommandLog() ) { - if (pSettings->debugger().showAnnotations()) { + if (pSettings->debugger().enableDebugConsole() ) { + if (pSettings->debugger().showDetailLog()) { for (const QString& line:mReader->fullOutput()) { pMainWindow->addDebugOutput(line); } @@ -506,6 +495,7 @@ void Debugger::syncFinishedParsing() if (mReader->signalReceived()) { SignalMessageDialog dialog(pMainWindow); + dialog.setOpenCPUInfo(pSettings->debugger().openCPUInfoWhenSignaled()); dialog.setMessage( tr("Signal \"%1\" Received: ").arg(mReader->signalName()) + "
" @@ -1119,9 +1109,9 @@ void DebugReader::runNextCmd() } // if devDebugger.ShowCommandLog or pCmd^.ShowInConsole then begin - if (pSettings->debugger().showCommandLog() ) { + if (pSettings->debugger().enableDebugConsole() ) { //update debug console - if (!pSettings->debugger().showAnnotations()) { + if (!pSettings->debugger().showDetailLog()) { emit changeDebugConsoleLastLine(pCmd->command + ' ' + pCmd->params); } else { emit changeDebugConsoleLastLine(pCmd->command + ' ' + pCmd->params); diff --git a/RedPandaIDE/debugger.h b/RedPandaIDE/debugger.h index 40ec39c2..39d4ceae 100644 --- a/RedPandaIDE/debugger.h +++ b/RedPandaIDE/debugger.h @@ -205,9 +205,6 @@ public: void notifyBeforeProcessWatchVar(); void notifyAfterProcessWatchVar(); - bool useUTF8() const; - void setUseUTF8(bool useUTF8); - BacktraceModel* backtraceModel(); BreakpointModel* breakpointModel(); bool executing() const; @@ -247,7 +244,6 @@ private: bool mExecuting; bool mCommandChanged; BreakpointModel *mBreakpointModel; - bool mUseUTF8; BacktraceModel *mBacktraceModel; WatchModel *mWatchModel; RegisterModel *mRegisterModel; diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 69090b43..7aa2184e 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -49,6 +49,14 @@ #include +static int findTabIndex(QTabWidget* tabWidget , QWidget* w) { + for (int i=0;icount();i++) { + if (w==tabWidget->widget(i)) + return i; + } + return -1; +} + MainWindow* pMainWindow; MainWindow::MainWindow(QWidget *parent) @@ -1056,6 +1064,18 @@ void MainWindow::updateDebuggerSettings() ui->debugConsole->setFont(font); ui->txtMemoryView->setFont(font); ui->txtLocals->setFont(font); + + int idx = findTabIndex(ui->debugViews,ui->tabDebugConsole); + if (idx>=0) { + if (!pSettings->debugger().enableDebugConsole()) { + ui->debugViews->removeTab(idx); + } + } else { + if (pSettings->debugger().enableDebugConsole()) { + ui->debugViews->insertTab(0, ui->tabDebugConsole, tr("Debug Console")); + } + } + } void MainWindow::checkSyntaxInBack(Editor *e) @@ -1398,7 +1418,6 @@ void MainWindow::debug() prepareDebugger(); - mDebugger->setUseUTF8(e->fileEncoding() == ENCODING_UTF8 || e->fileEncoding() == ENCODING_UTF8_BOM); if (!mDebugger->start()) return; mDebugger->sendCommand("-file-exec-and-symbols", QString("\"%1\"").arg(debugFile.filePath().replace('\\','/'))); @@ -1556,7 +1575,7 @@ void MainWindow::prepareDebugger() // Clear logs ui->debugConsole->clear(); - if (!pSettings->debugger().showCommandLog()) { + if (!pSettings->debugger().enableDebugConsole()) { ui->debugConsole->addLine("(gdb) "); } ui->txtEvalOutput->clear(); @@ -1927,13 +1946,13 @@ void MainWindow::buildContextMenus() ui->debugConsole->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->debugConsole,&QWidget::customContextMenuRequested, this, &MainWindow::onDebugConsoleContextMenu); - mDebugConsole_ShowCommandLog = createActionFor( - tr("Show debug logs in the debug console"), + mDebugConsole_ShowDetailLog = createActionFor( + tr("Show detail debug logs"), ui->debugConsole); - mDebugConsole_ShowCommandLog->setCheckable(true); - connect(mDebugConsole_ShowCommandLog, &QAction::toggled, + mDebugConsole_ShowDetailLog->setCheckable(true); + connect(mDebugConsole_ShowDetailLog, &QAction::toggled, [this]() { - pSettings->debugger().setShowCommandLog(mDebugConsole_ShowCommandLog->isChecked()); + pSettings->debugger().setShowDetailLog(mDebugConsole_ShowDetailLog->isChecked()); pSettings->debugger().save(); }); mDebugConsole_Copy=createActionFor( @@ -2615,16 +2634,16 @@ void MainWindow::onDebugConsoleContextMenu(const QPoint &pos) { QMenu menu(this); - bool oldBlock = mDebugConsole_ShowCommandLog->blockSignals(true); - mDebugConsole_ShowCommandLog->setChecked(pSettings->debugger().showCommandLog()); - mDebugConsole_ShowCommandLog->blockSignals(oldBlock); + bool oldBlock = mDebugConsole_ShowDetailLog->blockSignals(true); + mDebugConsole_ShowDetailLog->setChecked(pSettings->debugger().showDetailLog()); + mDebugConsole_ShowDetailLog->blockSignals(oldBlock); menu.addAction(mDebugConsole_Copy); menu.addAction(mDebugConsole_Paste); menu.addAction(mDebugConsole_SelectAll); menu.addAction(mDebugConsole_Clear); menu.addSeparator(); - menu.addAction(mDebugConsole_ShowCommandLog); + menu.addAction(mDebugConsole_ShowDetailLog); menu.exec(ui->debugConsole->mapToGlobal(pos)); } @@ -3704,7 +3723,7 @@ void MainWindow::cleanUpCPUDialog() void MainWindow::onDebugCommandInput(const QString& command) { if (mDebugger->executing()) { - mDebugger->sendCommand(command,""); + mDebugger->sendCommand(command,"", DebugCommandSource::Console); } } @@ -4854,14 +4873,6 @@ void MainWindow::updateEditorHideTime(QTabWidget* tabWidget) { } } -static int findTabIndex(QTabWidget* tabWidget , QWidget* w) { - for (int i=0;icount();i++) { - if (w==tabWidget->widget(i)) - return i; - } - return -1; -} - void MainWindow::showHideInfosTab(QWidget *widget, bool show) { int idx = findTabIndex(ui->tabInfos,widget); diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index 8e647ca4..75408571 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -633,7 +633,7 @@ private: QWidget * mFilesViewToolbar; //action for debug console - QAction * mDebugConsole_ShowCommandLog; + QAction * mDebugConsole_ShowDetailLog; QAction * mDebugConsole_Clear; QAction * mDebugConsole_Copy; QAction * mDebugConsole_Paste; diff --git a/RedPandaIDE/mainwindow.ui b/RedPandaIDE/mainwindow.ui index d45c3e17..e9d75868 100644 --- a/RedPandaIDE/mainwindow.ui +++ b/RedPandaIDE/mainwindow.ui @@ -506,7 +506,7 @@ QTabWidget::South - 0 + 2 diff --git a/RedPandaIDE/settings.cpp b/RedPandaIDE/settings.cpp index 29adba9e..b3896e40 100644 --- a/RedPandaIDE/settings.cpp +++ b/RedPandaIDE/settings.cpp @@ -2924,24 +2924,24 @@ Settings::Debugger::Debugger(Settings *settings):_Base(settings, SETTING_DEBUGGE } -bool Settings::Debugger::showCommandLog() const +bool Settings::Debugger::enableDebugConsole() const { - return mShowCommandLog; + return mEnableDebugConsole; } -void Settings::Debugger::setShowCommandLog(bool showCommandLog) +void Settings::Debugger::setEnableDebugConsole(bool showCommandLog) { - mShowCommandLog = showCommandLog; + mEnableDebugConsole = showCommandLog; } -bool Settings::Debugger::showAnnotations() const +bool Settings::Debugger::showDetailLog() const { - return mShowAnnotations; + return mShowDetailLog; } -void Settings::Debugger::setShowAnnotations(bool showAnnotations) +void Settings::Debugger::setShowDetailLog(bool showAnnotations) { - mShowAnnotations = showAnnotations; + mShowDetailLog = showAnnotations; } QString Settings::Debugger::fontName() const @@ -3004,6 +3004,16 @@ void Settings::Debugger::setAutosaveWatches(bool newAutosaveWatches) mAutosaveWatches = newAutosaveWatches; } +bool Settings::Debugger::openCPUInfoWhenSignaled() const +{ + return mOpenCPUInfoWhenSignaled; +} + +void Settings::Debugger::setOpenCPUInfoWhenSignaled(bool newOpenCPUInfoWhenSignaled) +{ + mOpenCPUInfoWhenSignaled = newOpenCPUInfoWhenSignaled; +} + bool Settings::Debugger::autosaveBreakpoints() const { return mAutosaveBreakpoints; @@ -3046,8 +3056,8 @@ void Settings::Debugger::setOnlyShowMono(bool onlyShowMono) void Settings::Debugger::doSave() { - saveValue("show_command_log", mShowCommandLog); - saveValue("show_annotations", mShowAnnotations); + saveValue("enable_debug_console", mEnableDebugConsole); + saveValue("show_detail_log", mShowDetailLog); saveValue("font_name",mFontName); saveValue("only_show_mono",mOnlyShowMono); saveValue("font_size",mFontSize); @@ -3058,13 +3068,14 @@ void Settings::Debugger::doSave() saveValue("skip_custom_lib", mSkipCustomLibraries); saveValue("autosave_breakpoints",mAutosaveBreakpoints); saveValue("autosave_watches",mAutosaveWatches); + saveValue("open_cpu_info_when_signaled",mOpenCPUInfoWhenSignaled); } void Settings::Debugger::doLoad() { - mShowCommandLog = boolValue("show_command_log",true); - mShowAnnotations = boolValue("show_annotations",false); + mEnableDebugConsole = boolValue("enable_debug_console",true); + mShowDetailLog = boolValue("show_detail_log",false); mFontName = stringValue("font_name","Consolas"); mOnlyShowMono = boolValue("only_show_mono",true); mFontSize = intValue("font_size",12); @@ -3075,6 +3086,7 @@ void Settings::Debugger::doLoad() mSkipCustomLibraries = boolValue("skip_custom_lib",false); mAutosaveBreakpoints = boolValue("autosave_breakpoints",true); mAutosaveWatches = boolValue("autosave_watches",true); + mOpenCPUInfoWhenSignaled = boolValue("open_cpu_info_when_signaled",true); } Settings::History::History(Settings *settings):_Base(settings, SETTING_HISTORY) diff --git a/RedPandaIDE/settings.h b/RedPandaIDE/settings.h index 23bfb885..3bc1450b 100644 --- a/RedPandaIDE/settings.h +++ b/RedPandaIDE/settings.h @@ -930,11 +930,11 @@ public: class Debugger: public _Base { public: explicit Debugger(Settings* settings); - bool showCommandLog() const; - void setShowCommandLog(bool showCommandLog); + bool enableDebugConsole() const; + void setEnableDebugConsole(bool showCommandLog); - bool showAnnotations() const; - void setShowAnnotations(bool showAnnotations); + bool showDetailLog() const; + void setShowDetailLog(bool showAnnotations); bool onlyShowMono() const; void setOnlyShowMono(bool onlyShowMono); @@ -964,9 +964,12 @@ public: bool autosaveWatches() const; void setAutosaveWatches(bool newAutosaveWatches); + bool openCPUInfoWhenSignaled() const; + void setOpenCPUInfoWhenSignaled(bool newOpenCPUInfoWhenSignaled); + private: - bool mShowCommandLog; - bool mShowAnnotations; + bool mEnableDebugConsole; + bool mShowDetailLog; QString mFontName; bool mOnlyShowMono; int mFontSize; @@ -977,6 +980,7 @@ public: bool mSkipCustomLibraries; bool mAutosaveBreakpoints; bool mAutosaveWatches; + bool mOpenCPUInfoWhenSignaled; // _Base interface protected: diff --git a/RedPandaIDE/settingsdialog/debuggeneralwidget.cpp b/RedPandaIDE/settingsdialog/debuggeneralwidget.cpp index b4255ed7..a14a0975 100644 --- a/RedPandaIDE/settingsdialog/debuggeneralwidget.cpp +++ b/RedPandaIDE/settingsdialog/debuggeneralwidget.cpp @@ -20,13 +20,14 @@ void DebugGeneralWidget::doLoad() ui->chkOnlyMono->setChecked(pSettings->debugger().onlyShowMono()); ui->cbFont->setCurrentFont(QFont(pSettings->debugger().fontName())); ui->sbFontSize->setValue(pSettings->debugger().fontSize()); - ui->chkShowLog->setChecked(pSettings->debugger().showCommandLog()); - ui->chkShowFullAnnotation->setChecked(pSettings->debugger().showAnnotations()); + ui->grpEnableDebugConsole->setChecked(pSettings->debugger().enableDebugConsole()); + ui->chkShowDetailLog->setChecked(pSettings->debugger().showDetailLog()); if (pSettings->debugger().useIntelStyle()) { ui->rbIntel->setChecked(true); } else { ui->rbATT->setChecked(true); } + ui->chkShowCPUWhenSignaled->setChecked(pSettings->debugger().openCPUInfoWhenSignaled()); ui->chkBlendMode->setChecked(pSettings->debugger().blendMode()); ui->chkSkipSystemLib->setChecked(pSettings->debugger().skipSystemLibraries()); ui->chkSkipProjectLib->setChecked(pSettings->debugger().skipProjectLibraries()); @@ -40,8 +41,9 @@ void DebugGeneralWidget::doSave() pSettings->debugger().setOnlyShowMono(ui->chkOnlyMono->isChecked()); pSettings->debugger().setFontName(ui->cbFont->currentFont().family()); pSettings->debugger().setFontSize(ui->sbFontSize->value()); - pSettings->debugger().setShowCommandLog(ui->chkShowLog->isChecked()); - pSettings->debugger().setShowAnnotations(ui->chkShowFullAnnotation->isChecked()); + pSettings->debugger().setEnableDebugConsole(ui->grpEnableDebugConsole->isChecked()); + pSettings->debugger().setShowDetailLog(ui->chkShowDetailLog->isChecked()); + pSettings->debugger().setOpenCPUInfoWhenSignaled(ui->chkShowCPUWhenSignaled); pSettings->debugger().setUseIntelStyle(ui->rbIntel->isChecked()); pSettings->debugger().setBlendMode(ui->chkBlendMode->isChecked()); pSettings->debugger().setSkipSystemLibraries(ui->chkSkipSystemLib->isChecked()); diff --git a/RedPandaIDE/settingsdialog/debuggeneralwidget.ui b/RedPandaIDE/settingsdialog/debuggeneralwidget.ui index 00be2fab..19a9a28a 100644 --- a/RedPandaIDE/settingsdialog/debuggeneralwidget.ui +++ b/RedPandaIDE/settingsdialog/debuggeneralwidget.ui @@ -6,7 +6,7 @@ 0 0 - 677 + 704 563 @@ -36,7 +36,7 @@ - + Debug Console @@ -143,16 +143,9 @@ - + - Show debug logs in the debug console - - - - - - - Show full gdb annotations + Show detail debug logs @@ -182,6 +175,13 @@ + + + + Show CPU Window when signal received + + + diff --git a/RedPandaIDE/widgets/signalmessagedialog.cpp b/RedPandaIDE/widgets/signalmessagedialog.cpp index b44e5730..e94acb85 100644 --- a/RedPandaIDE/widgets/signalmessagedialog.cpp +++ b/RedPandaIDE/widgets/signalmessagedialog.cpp @@ -22,3 +22,8 @@ bool SignalMessageDialog::openCPUInfo() { return ui->chkOpenCPUInfo->isChecked(); } + +void SignalMessageDialog::setOpenCPUInfo(bool value) +{ + ui->chkOpenCPUInfo->setChecked(value); +} diff --git a/RedPandaIDE/widgets/signalmessagedialog.h b/RedPandaIDE/widgets/signalmessagedialog.h index f7781fcf..a0fd4fb6 100644 --- a/RedPandaIDE/widgets/signalmessagedialog.h +++ b/RedPandaIDE/widgets/signalmessagedialog.h @@ -16,6 +16,7 @@ public: ~SignalMessageDialog(); void setMessage(const QString& message); bool openCPUInfo(); + void setOpenCPUInfo(bool value); private: Ui::SignalMessageDialog *ui; From 39ab3884582cc93a5f3c543c045a73c8423ad32f Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Thu, 25 Nov 2021 11:24:38 +0800 Subject: [PATCH 21/32] work save --- RedPandaIDE/debugger.cpp | 67 ++++++++++++++++++++------------- RedPandaIDE/debugger.h | 15 ++++++-- RedPandaIDE/gdbmiresultparser.h | 4 +- 3 files changed, 55 insertions(+), 31 deletions(-) diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index d6c1ab53..f371f8c7 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -288,9 +288,10 @@ void Debugger::addWatchVar(const QString &namein) PWatchVar var = std::make_shared(); var->parent= nullptr; - var->name = namein; + var->expression = namein; var->value = tr("Execute to evaluate"); - var->gdbIndex = -1; + var->numChild = 0; + var->hasMore = false; mWatchModel->addWatchVar(var); sendWatchCommand(var); @@ -412,12 +413,12 @@ BreakpointModel *Debugger::breakpointModel() void Debugger::sendWatchCommand(PWatchVar var) { - sendCommand("display", var->name); + sendCommand("-var-carete", QString(" - %1").arg(var->expression)); } void Debugger::sendRemoveWatchCommand(PWatchVar var) { - sendCommand("undisplay",QString("%1").arg(var->gdbIndex)); + sendCommand("-var-delete",QString("%1").arg(var->name)); } void Debugger::sendBreakpointCommand(PBreakpoint breakpoint) @@ -1812,8 +1813,10 @@ QVariant WatchModel::data(const QModelIndex &index, int role) const //qDebug()<<"item->text:"<text; switch(index.column()) { case 0: - return item->name; + return item->expression; case 1: + return item->type; + case 2: return item->value; } } @@ -1884,13 +1887,13 @@ int WatchModel::rowCount(const QModelIndex &parent) const int WatchModel::columnCount(const QModelIndex&) const { - return 2; + return 3; } void WatchModel::addWatchVar(PWatchVar watchVar) { for (PWatchVar var:mWatchVars) { - if (watchVar->name == var->name) { + if (watchVar->expression == var->expression) { return; } } @@ -1899,25 +1902,11 @@ void WatchModel::addWatchVar(PWatchVar watchVar) this->endInsertRows(); } -void WatchModel::removeWatchVar(const QString &name) +void WatchModel::removeWatchVar(const QString &express) { for (int i=mWatchVars.size()-1;i>=0;i--) { PWatchVar var = mWatchVars[i]; - if (name == var->name) { - this->beginResetModel(); - //this->beginRemoveRows(QModelIndex(),i,i); - mWatchVars.removeAt(i); - //this->endRemoveRows(); - this->endResetModel(); - } - } -} - -void WatchModel::removeWatchVar(int gdbIndex) -{ - for (int i=mWatchVars.size()-1;i>=0;i--) { - PWatchVar var = mWatchVars[i]; - if (gdbIndex == var->gdbIndex) { + if (express == var->expression) { this->beginResetModel(); //this->beginRemoveRows(QModelIndex(),i,i); mWatchVars.removeAt(i); @@ -2006,7 +1995,7 @@ void WatchModel::save(const QString &filename) QJsonArray array; foreach (const PWatchVar& watchVar, mWatchVars) { QJsonObject obj; - obj["name"]=watchVar->name; + obj["expression"]=watchVar->expression; array.append(obj); } QJsonDocument doc; @@ -2043,9 +2032,10 @@ void WatchModel::load(const QString &filename) QJsonObject obj=value.toObject(); PWatchVar var = std::make_shared(); var->parent= nullptr; - var->name = obj["name"].toString(); + var->expression = obj["expression"].toString(); var->value = tr("Execute to evaluate"); - var->gdbIndex = -1; + var->numChild = 0; + var->hasMore=false; addWatchVar(var); } @@ -2063,12 +2053,37 @@ QVariant WatchModel::headerData(int section, Qt::Orientation orientation, int ro case 0: return tr("Expression"); case 1: + return tr("Type"); + case 2: return tr("Value"); } } return QVariant(); } +void WatchModel::fetchMore(const QModelIndex &parent) +{ + //todo +} + +bool WatchModel::canFetchMore(const QModelIndex &parent) const +{ + if (!parent.isValid()) { + return false; + } + WatchVar* item = static_cast(parent.internalPointer()); + return item->numChild>item->children.count(); +} + +bool WatchModel::hasChildren(const QModelIndex &parent) const +{ + if (!parent.isValid()) { + return false; + } + WatchVar* item = static_cast(parent.internalPointer()); + return item->numChild>0; +} + RegisterModel::RegisterModel(QObject *parent):QAbstractTableModel(parent) { diff --git a/RedPandaIDE/debugger.h b/RedPandaIDE/debugger.h index 39d4ceae..345a6093 100644 --- a/RedPandaIDE/debugger.h +++ b/RedPandaIDE/debugger.h @@ -31,9 +31,11 @@ struct WatchVar; using PWatchVar = std::shared_ptr; struct WatchVar { QString name; + QString expression; + bool hasMore; QString value; - QString fullName; - int gdbIndex; + QString type; + int numChild; QList children; WatchVar * parent; //use raw point to prevent circular-reference }; @@ -133,8 +135,7 @@ public: int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; void addWatchVar(PWatchVar watchVar); - void removeWatchVar(const QString& name); - void removeWatchVar(int gdbIndex); + void removeWatchVar(const QString& expression); void removeWatchVar(const QModelIndex& index); void clear(); const QList& watchVars(); @@ -152,6 +153,12 @@ private: // QAbstractItemModel interface public: QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + void fetchMore(const QModelIndex &parent); + bool canFetchMore(const QModelIndex &parent) const; + + // QAbstractItemModel interface +public: + bool hasChildren(const QModelIndex &parent) const; }; diff --git a/RedPandaIDE/gdbmiresultparser.h b/RedPandaIDE/gdbmiresultparser.h index f057ef2a..4b0964b8 100644 --- a/RedPandaIDE/gdbmiresultparser.h +++ b/RedPandaIDE/gdbmiresultparser.h @@ -18,7 +18,9 @@ enum class GDBMIResultType { Evaluation, RegisterNames, RegisterValues, - Memory + Memory, + VariableInfo, + }; From 92fcd9b923d925f01aa87467b669d61a758c5310 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Thu, 25 Nov 2021 20:26:43 +0800 Subject: [PATCH 22/32] implemented: watch var handles --- NEWS.md | 4 + RedPandaIDE/RedPandaIDE_zh_CN.qm | Bin 106714 -> 106748 bytes RedPandaIDE/RedPandaIDE_zh_CN.ts | 375 +++++++++---------- RedPandaIDE/debugger.cpp | 577 +++++++++++++++--------------- RedPandaIDE/debugger.h | 87 +++-- RedPandaIDE/gdbmiresultparser.cpp | 8 +- RedPandaIDE/gdbmiresultparser.h | 5 +- RedPandaIDE/mainwindow.cpp | 17 +- RedPandaIDE/mainwindow.ui | 4 +- RedPandaIDE/version.h | 2 +- 10 files changed, 555 insertions(+), 524 deletions(-) diff --git a/NEWS.md b/NEWS.md index 0a9732f6..9fce4961 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +Version 0.10.0 For Dev-C++ 7 Beta + - enhancement: use gdb/mi interface to communicate with gdb debug session + - enhancement: better display of watch vars + Version 0.9.3 For Dev-C++ 7 Beta - fix: the count in the title of issues view isn't correct - fix: columns calculation not correct when paint lines containing chinese characters diff --git a/RedPandaIDE/RedPandaIDE_zh_CN.qm b/RedPandaIDE/RedPandaIDE_zh_CN.qm index 751c4090e99fd5c582d14f73c906fa6c473fcb3b..18a0af6e662aae3f6e32b6f353104435b0ee1394 100644 GIT binary patch delta 9923 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ǽJe~7WVnv?2Id2iJ)a*OwBX%Rof5iFtz+SeY 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 F{2yL2`qKaa diff --git a/RedPandaIDE/RedPandaIDE_zh_CN.ts b/RedPandaIDE/RedPandaIDE_zh_CN.ts index dd35d1e5..239e2e49 100644 --- a/RedPandaIDE/RedPandaIDE_zh_CN.ts +++ b/RedPandaIDE/RedPandaIDE_zh_CN.ts @@ -95,17 +95,17 @@ BacktraceModel - + Function 函数 - + Filename 文件名 - + Line @@ -151,37 +151,37 @@ BreakpointModel - + Filename 文件名 - + Line - + Condition 条件 - + Save file '%1' failed. 保存文件'%1'失败。 - + Can't open file '%1' for write. 无法写入文件'%1'. - + Error in json file '%1':%2 : %3 JSON文件'%1':%2中存在错误:%3 - + Can't open file '%1' for read. 无法读取文件'%1'. @@ -952,73 +952,71 @@ Are you really want to continue? Debugger - + No compiler set 无编译器设置 - + No compiler set is configured. 没有配置编译器设置。 - + Can't start debugging. 无法启动调试器 - + Debugger path error 调试路径错误 - + Debugger's path "%1" contains non-ascii characters. 调试路径"%1"中包含非ASCII字符(如,中文字符) - + This prevents it from executing. 这会导致调试器无法启动。 - + Debugger not exists 找不到调试器 - + Can''t find debugger in : "%1" 找不到调试器程序"%1" - - + Execute to evaluate 执行以求值 - Not found in current context - 不在当前语境中 + 不在当前语境中 - + Compile 编译 - + Source file is more recent than executable. 源文件比程序文件新。 - + Recompile? 重新编译? - + Signal "%1" Received: 收到信号"%1": @@ -2867,11 +2865,11 @@ Are you really want to continue? - + + - - - + + Issues 编译器 @@ -3128,8 +3126,8 @@ Are you really want to continue?
- - + + Copy 复制 @@ -3140,7 +3138,7 @@ Are you really want to continue? - + Paste 粘贴 @@ -3151,7 +3149,7 @@ Are you really want to continue? - + Select All 选择全部 @@ -3278,7 +3276,7 @@ Are you really want to continue? - + New Problem Set 新建试题集 @@ -3297,14 +3295,14 @@ Are you really want to continue? - + Save Problem Set 保存试题集 - + Load Problem Set 载入试题集 @@ -3639,7 +3637,7 @@ Are you really want to continue? - + Clear all breakpoints 删除所有断点 @@ -3740,7 +3738,7 @@ Are you really want to continue? - + Rename Symbol 重命名符号 @@ -3761,13 +3759,13 @@ Are you really want to continue? - + Export As RTF 导出为RTF - + Export As HTML 导出为HTML @@ -3887,7 +3885,7 @@ Are you really want to continue? - + Open Folder 打开文件夹 @@ -3897,7 +3895,7 @@ Are you really want to continue? 运行参数... - + File Encoding 文件编码 @@ -4070,44 +4068,44 @@ Are you really want to continue? 重新编译? - - + + Save last open info error 保存上次打开信息失败 - + Can't remove old last open information file '%1' 无法删除旧上次打开信息文件'%1' - + Can't save last open info file '%1' 无法保存上次打开信息文件'%1' - + Load last open info error 载入上次打开信息失败 - + Can't load last open info file '%1' 无法载入上次打开信息文件'%1' - + Show detail debug logs 显示详细调试器日志 - + Copy all 全部复制 - - + + Clear 清除 @@ -4123,7 +4121,7 @@ Are you really want to continue? - + Problem Set %1 试题集%1 @@ -4161,56 +4159,56 @@ Are you really want to continue? 项目已经被修改过,是否需要重新构建? - + Auto Save Error 自动保存出错 - + Auto save "%1" to "%2" failed:%3 自动保存"%1"到"%2"失败:%3 - + Properties... 试题属性... - + Set Problem Set Name 设置试题集名称 - + Problem Set Name: 试题集名称: - + Remove 删除 - + Remove All Bookmarks 删除全部书签 - + Modify Description 修改描述 - - - + + + Bookmark Description 书签描述 - - - + + + Description: 描述: @@ -4219,363 +4217,363 @@ Are you really want to continue? 在调试主控台中显示调试器输出 - + Remove this search 清除这次搜索 - + Clear all searches 删除所有搜索 - + Breakpoint condition... 断点条件... - + Break point condition 断点条件 - + Enter the condition of the breakpoint: 输入当前断点的生效条件: - + Remove All Breakpoints Remove all breakpoints 删除所有断点 - + Remove Breakpoint 删除当前断点 - + Rename File 重命名文件 - - + + Add Folder 添加文件夹 - + New folder 新文件夹 - + Folder name: 文件夹: - + Rename Folder 重命名 - + Remove Folder 删除文件夹 - + Sort By Type 按类型排序 - + Sort alphabetically 按名称排序 - + Show inherited members 显示继承的成员 - + Goto declaration 跳转到声明处 - + Goto definition 跳转到定义处 - + Open in Editor 在编辑器中打开 - + Open in External Program 使用外部程序打开 - + Open in Terminal 在终端中打开 - + Open in Windows Explorer 在Windows浏览器中打开 - + Character sets 字符集 - + %1 files autosaved 已自动保存%1个文件 - + Set answer to... 设置答案源代码... - + select other file... 选择其他文件... - + Select Answer Source File 选择答案源代码文件 - + C/C++Source Files (*.c *.cpp *.cc *.cxx) C/C++Source Files (*.c *.cpp *.cc *.cxx C/C++源代码文件 (*.c *.cpp *.cc *.cxx) - + Save project 保存项目 - + The project '%1' has modifications. 项目'%1'有改动。 - - + + Do you want to save it? 需要保存吗? - - + + File Changed 文件已发生变化 - + New Project File? 新建项目文件? - + Do you want to add the new file to the project? 您是否要将新建的文件加入项目? - - - - + + + + Save Error 保存失败 - + Change Project Compiler Set 改变项目编译器配置集 - + Change the project's compiler set will lose all custom compiler set options. 改变项目的编译器配置集会导致所有的自定义编译器选项被重置。 - + Do you really want to do that? 你真的想要做那些吗? - + Do you really want to clear all breakpoints in this file? 您真的要清除该文件的所有断点吗? - + New project 新建项目 - + Close %1 and start new project? 关闭'%1'以打开新项目? - + Folder not exist 文件夹不存在 - + Folder '%1' doesn't exist. Create it now? 文件夹'%1'不存在。是否创建? - + Can't create folder 无法创建文件夹 - + Failed to create folder '%1'. 创建文件夹'%1'失败。 - + Save new project as - + Red panda Dev-C++ project file (*.dev) 小熊猫Dev-C++项目文件 (*.dev) - + New project fail 新建项目失败 - + Can't assign project template 无法使用模板创建项目 - + Remove file 删除文件 - + Remove the file from disk? 同时从硬盘上删除文件? - + untitled 无标题 - + New Project File Name 新的项目文件名 - + File Name: 文件名: - + File Already Exists! 文件已存在! - + File '%1' already exists! 文件'%1'已经存在! - + Add to project 添加到项目 - + Rename Error 重命名出错 - + Symbol '%1' is defined in system header. 符号'%1'在系统头文件中定义,无法修改。 - + New Name 新名称 - - + + Replace Error 替换出错 - + Can't open file '%1' for replace! 无法打开文件'%1'进行替换! - + Contents has changed since last search! 内容和上次查找时不一致。 - + Rich Text Format Files (*.rtf) RTF格式文件 (*.rtf) - + HTML Files (*.html) HTML文件 (*.html) - + The current problem set is not empty. 当前的试题集不是空的。 - + Problem %1 试题%1 - - + + Problem Set Files (*.pbs) 试题集文件 (*.pbs) - + Load Error 载入失败 - - + + Problem Case %1 试题案例%1 @@ -4587,14 +4585,14 @@ Are you really want to continue? - - - - - - - - + + + + + + + + Error 错误 @@ -4604,75 +4602,75 @@ Are you really want to continue? 项目历史 - + File '%1' was changed. 磁盘文件'%1'已被修改。 - + Reload its content from disk? 是否重新读取它的内容? - + File '%1' was removed. 磁盘文件'%1'已被删除。 - + Keep it open? 是否保持它在小熊猫C++中打开的编辑窗口? - + Open 打开 - + Compile Failed 编译失败 - + Run Failed 运行失败 - - + + Confirm Convertion 确认转换 - - + + The editing file will be saved using %1 encoding. <br />This operation can't be reverted. <br />Are you sure to continue? 当前编辑器中的文件将会使用%1编码保存。<br />这项操作无法被撤回。<br />你确定要继续吗? - + New Watch Expression 新监视表达式 - + Enter Watch Expression (it is recommended to use 'this->' for class members): 输入监视表达式 - + Parsing file %1 of %2: "%3" (%1/%2)正在解析文件"%3" - - + + Done parsing %1 files in %2 seconds 完成%1个文件的解析,用时%2秒 - + (%1 files per second) (每秒%1个文件) @@ -6188,12 +6186,12 @@ Are you really want to continue? RegisterModel - + Register 寄存器 - + Value @@ -6600,7 +6598,7 @@ Are you really want to continue? 自动链接 - + @@ -6676,7 +6674,7 @@ Are you really want to continue? 杂项 - + Program Runner @@ -7089,37 +7087,48 @@ Are you really want to continue? WatchModel - + Save file '%1' failed. 保存文件'%1'失败。 - + Can't open file '%1' for write. 无法写入文件'%1'. - + Error in json file '%1':%2 : %3 JSON文件'%1':%2中存在错误:%3 - + + Execute to evaluate 执行以求值 - + + Not Valid + 在当前作用域中无效 + + + Can't open file '%1' for read. 无法读取文件'%1'. - + Expression 表达式 - + + Type + 类型 + + + Value diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index f371f8c7..06f6ae10 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -27,6 +27,9 @@ Debugger::Debugger(QObject *parent) : QObject(parent) mReader = nullptr; mCommandChanged = false; mLeftPageIndexBackup = -1; + + connect(mWatchModel, &WatchModel::fetchChildren, + this, &Debugger::fetchVarChildren); } bool Debugger::start() @@ -58,6 +61,7 @@ bool Debugger::start() tr("Can''t find debugger in : \"%1\"").arg(debuggerPath)); return false; } + mWatchModel->resetAllVarInfos(); mReader = new DebugReader(this); mReader->setDebuggerPath(debuggerPath); connect(mReader, &QThread::finished,this,&Debugger::clearUpReader); @@ -81,10 +85,20 @@ bool Debugger::start() &Debugger::updateRegisterNames); connect(mReader, &DebugReader::registerValuesUpdated, this, &Debugger::updateRegisterValues); + connect(mReader, &DebugReader::varCreated,mWatchModel, + &WatchModel::updateVarInfo); + connect(mReader, &DebugReader::prepareVarChildren,mWatchModel, + &WatchModel::prepareVarChildren); + connect(mReader, &DebugReader::addVarChild,mWatchModel, + &WatchModel::addVarChild); + connect(mReader, &DebugReader::varValueUpdated,mWatchModel, + &WatchModel::updateVarValue); connect(mReader, &DebugReader::inferiorContinued,pMainWindow, &MainWindow::removeActiveBreakpoints); connect(mReader, &DebugReader::inferiorStopped,pMainWindow, &MainWindow::setActiveBreakpoint); + connect(mReader, &DebugReader::inferiorStopped,this, + &Debugger::refreshWatchVars); mReader->registerInferiorStoppedCommand("-stack-list-frames",""); mReader->registerInferiorStoppedCommand("-stack-list-variables", "--all-values"); @@ -110,10 +124,6 @@ void Debugger::clearUpReader() mReader->deleteLater(); mReader=nullptr; -// if WatchVarList.Count = 0 then // nothing worth showing, restore view -// MainForm.LeftPageControl.ActivePageIndex := LeftPageIndexBackup; - -// // Close CPU window if (pMainWindow->cpuDialog()!=nullptr) { pMainWindow->cpuDialog()->close(); } @@ -129,9 +139,9 @@ void Debugger::clearUpReader() mBacktraceModel->clear(); - for(PWatchVar var:mWatchModel->watchVars()) { - invalidateWatchVar(var); - } + mWatchModel->clearAllVarInfos(); + + mBreakpointModel->invalidateAllBreakpointNumbers(); pMainWindow->updateEditorActions(); } @@ -279,37 +289,43 @@ void Debugger::sendAllBreakpointsToDebugger() } } -void Debugger::addWatchVar(const QString &namein) +void Debugger::addWatchVar(const QString &expression) { // Don't allow duplicates... - PWatchVar oldVar = mWatchModel->findWatchVar(namein); + PWatchVar oldVar = mWatchModel->findWatchVar(expression); if (oldVar) return; PWatchVar var = std::make_shared(); var->parent= nullptr; - var->expression = namein; + var->expression = expression; var->value = tr("Execute to evaluate"); var->numChild = 0; var->hasMore = false; + var->parent = nullptr; mWatchModel->addWatchVar(var); sendWatchCommand(var); } -void Debugger::renameWatchVar(const QString &oldname, const QString &newname) +void Debugger::modifyWatchVarExpression(const QString &oldExpr, const QString &newExpr) { // check if name already exists; - PWatchVar var = mWatchModel->findWatchVar(newname); + PWatchVar var = mWatchModel->findWatchVar(newExpr); if (var) return; - var = mWatchModel->findWatchVar(oldname); + var = mWatchModel->findWatchVar(oldExpr); if (var) { - var->name = newname; - if (mExecuting && var->gdbIndex!=-1) + if (mExecuting && !var->expression.isEmpty()) sendRemoveWatchCommand(var); - invalidateWatchVar(var); + var->expression = newExpr; + var->type.clear(); + var->value.clear(); + var->hasMore = false; + var->numChild=0; + var->name.clear(); + var->children.clear(); if (mExecuting) { sendWatchCommand(var); @@ -319,9 +335,16 @@ void Debugger::renameWatchVar(const QString &oldname, const QString &newname) void Debugger::refreshWatchVars() { - for (PWatchVar var:mWatchModel->watchVars()) { - if (var->gdbIndex == -1) - sendWatchCommand(var); + if (mExecuting) { + sendAllWatchVarsToDebugger(); + sendCommand("-var-update"," --all-values *"); + } +} + +void Debugger::fetchVarChildren(const QString &varName) +{ + if (mExecuting) { + sendCommand("-var-list-children",varName); } } @@ -332,75 +355,37 @@ void Debugger::removeWatchVars(bool deleteparent) } else { for(const PWatchVar& var:mWatchModel->watchVars()) { sendRemoveWatchCommand(var); - invalidateWatchVar(var); } + mWatchModel->clearAllVarInfos(); } } void Debugger::removeWatchVar(const QModelIndex &index) { + PWatchVar var = mWatchModel->findWatchVar(index); + if (!var) + return; + sendRemoveWatchCommand(var); mWatchModel->removeWatchVar(index); } -void Debugger::invalidateAllVars() -{ - mReader->setInvalidateAllVars(true); -} - -void Debugger::sendAllWatchvarsToDebugger() +void Debugger::sendAllWatchVarsToDebugger() { for (PWatchVar var:mWatchModel->watchVars()) { - sendWatchCommand(var); + if (var->name.isEmpty()) + sendWatchCommand(var); } } -void Debugger::invalidateWatchVar(const QString &name) +PWatchVar Debugger::findWatchVar(const QString &expression) { - PWatchVar var = mWatchModel->findWatchVar(name); - if (var) { - invalidateWatchVar(var); - } -} - -void Debugger::invalidateWatchVar(PWatchVar var) -{ - var->gdbIndex = -1; - QString value; - if (mExecuting) { - value = tr("Not found in current context"); - } else { - value = tr("Execute to evaluate"); - } - var->value = value; - if (var->children.isEmpty()) { - mWatchModel->notifyUpdated(var); - } else { - mWatchModel->beginUpdate(); - var->children.clear(); - mWatchModel->endUpdate(); - } -} - -PWatchVar Debugger::findWatchVar(const QString &name) -{ - return mWatchModel->findWatchVar(name); + return mWatchModel->findWatchVar(expression); } //void Debugger::notifyWatchVarUpdated(PWatchVar var) //{ // mWatchModel->notifyUpdated(var); //} - -void Debugger::notifyBeforeProcessWatchVar() -{ - mWatchModel->beginUpdate(); -} - -void Debugger::notifyAfterProcessWatchVar() -{ - mWatchModel->endUpdate(); -} - BacktraceModel* Debugger::backtraceModel() { return mBacktraceModel; @@ -413,7 +398,7 @@ BreakpointModel *Debugger::breakpointModel() void Debugger::sendWatchCommand(PWatchVar var) { - sendCommand("-var-carete", QString(" - %1").arg(var->expression)); + sendCommand("-var-create", var->expression); } void Debugger::sendRemoveWatchCommand(PWatchVar var) @@ -587,7 +572,6 @@ DebugReader::DebugReader(Debugger* debugger, QObject *parent) : QThread(parent), mDebugger = debugger; mProcess = nullptr; mCmdRunning = false; - mInvalidateAllVars = false; } void DebugReader::postCommand(const QString &Command, const QString &Params, @@ -740,6 +724,15 @@ void DebugReader::processResult(const QByteArray &result) case GDBMIResultType::RegisterValues: handleRegisterValue(multiValues["register-values"].array()); return; + case GDBMIResultType::CreateVar: + handleCreateVar(multiValues); + return; + case GDBMIResultType::ListVarChildren: + handleListVarChildren(multiValues); + return; + case GDBMIResultType::UpdateVarValue: + handleUpdateVarValue(multiValues["changelist"].array()); + return; } } @@ -846,12 +839,6 @@ void DebugReader::processDebugOutput(const QByteArray& debugOutput) // Only update once per update at most //WatchView.Items.BeginUpdate; - if (mInvalidateAllVars) { - //invalidate all vars when there's first output - mDebugger->removeWatchVars(false); - mInvalidateAllVars = false; - } - emit parseStarted(); mConsoleOutput.clear(); @@ -899,190 +886,6 @@ void DebugReader::runInferiorStoppedHook() } } -QString DebugReader::processEvalOutput() -{ - int indent = 0; - - // First line gets special treatment - QString result =""; - if (result.startsWith('{')) - indent+=4; - - // Collect all data, add formatting in between -// AnnotationType nextAnnotation; -// QString nextLine; -// bool shouldExit = false; -// do { -// nextAnnotation = getNextAnnotation(); -// nextLine = getNextLine(); -// switch(nextAnnotation) { -// // Change indent if { or } is found -// case AnnotationType::TFieldBegin: -// result += "\r\n" + QString(4,' '); -// break; -// case AnnotationType::TFieldValue: -// if (nextLine.startsWith('{') && (peekNextAnnotation() != -// AnnotationType::TArrayBegin)) -// indent+=4; -// break; -// case AnnotationType::TFieldEnd: -// if (nextLine.endsWith('}')) { -// indent-=4; -// result += "\r\n" + QString(4,' '); -// } -// break; -// case AnnotationType::TEOF: -// case AnnotationType::TValueHistoryEnd: -// case AnnotationType::TDisplayEnd: -// shouldExit = true; -// default: -// break; -// } -// result += nextLine; -// } while (!shouldExit); - return result; -} - -void DebugReader::processWatchOutput(PWatchVar watchVar) -{ -// // Expand if it was expanded or if it didn't have any children -// bool ParentWasExpanded = false; - - // Do not remove root node of watch variable - - watchVar->children.clear(); - watchVar->value = ""; - // Process output parsed by ProcessEvalStruct - QString s = processEvalOutput(); - - QStringList tokens = tokenize(s); - PWatchVar parentVar = watchVar; - PWatchVar currentVar = watchVar; - - QVector varStack; - int i=0; - while (i='a' && ch<='z') - || (ch>='A' && ch<='Z') || (ch>127)) { - //is identifier,create new child node - PWatchVar newVar = std::make_shared(); - newVar->parent = parentVar.get(); - newVar->name = token; - newVar->fullName = parentVar->fullName + '.'+token; - newVar->value = ""; - newVar->gdbIndex = -1; - parentVar->children.append(newVar); - currentVar = newVar; - } else if (ch == '{') { - if (parentVar->value.isEmpty()) { - parentVar->value = "{"; - } else { - PWatchVar newVar = std::make_shared(); - newVar->parent = parentVar.get(); - if (parentVar) { - int count = parentVar->children.count(); - newVar->name = QString("[%1]").arg(count); - newVar->fullName = parentVar->fullName + newVar->name; - } else { - newVar->name = QString("[0]"); - newVar->fullName = newVar->name; - } - newVar->value = "{"; - parentVar->children.append(newVar); - varStack.push_back(parentVar); - parentVar = newVar; - } - currentVar = nullptr; - } else if (ch == '}') { - currentVar = nullptr; - PWatchVar newVar = std::make_shared(); - newVar->parent = parentVar.get(); - newVar->name = ""; - newVar->value = "}"; - newVar->gdbIndex = -1; - parentVar->children.append(newVar); - if (!varStack.isEmpty()) { - parentVar = varStack.back(); - varStack.pop_back(); - } - } else if (ch == '=') { - // just skip it - } else if (ch == ',') { - currentVar = nullptr; - } else { - if (currentVar) { - if (currentVar->value.isEmpty()) { - currentVar->value = token; - } else { - currentVar->value += " "+token; - } - } else { - PWatchVar newVar = std::make_shared(); - newVar->parent = parentVar.get(); - newVar->name = QString("[%1]") - .arg(parentVar->children.count()); - newVar->fullName = parentVar->fullName + newVar->name; - newVar->value = token; - newVar->gdbIndex = -1; - parentVar->children.append(newVar); - } - } - i++; - } - // add placeholder name for variable name so we can format structs using one rule - - // Add children based on indent -// QStringList lines = TextToLines(s); - -// for (const QString& line:lines) { -// // Format node text. Remove trailing comma -// QString nodeText = line.trimmed(); -// if (nodeText.endsWith(',')) { -// nodeText.remove(nodeText.length()-1,1); -// } - -// if (nodeText.endsWith('{')) { // new member struct -// if (parentVar->text.isEmpty()) { // root node, replace text only -// parentVar->text = nodeText; -// } else { -// PWatchVar newVar = std::make_shared(); -// newVar->parent = parentVar.get(); -// newVar->name = ""; -// newVar->text = nodeText; -// newVar->gdbIndex = -1; -// parentVar->children.append(newVar); -// varStack.push_back(parentVar); -// parentVar = newVar; -// } -// } else if (nodeText.startsWith('}')) { // end of struct, change parent -// PWatchVar newVar = std::make_shared(); -// newVar->parent = parentVar.get(); -// newVar->name = ""; -// newVar->text = "}"; -// newVar->gdbIndex = -1; -// parentVar->children.append(newVar); -// if (!varStack.isEmpty()) { -// parentVar = varStack.back(); -// varStack.pop_back(); -// } -// } else { // next parent member/child -// if (parentVar->text.isEmpty()) { // root node, replace text only -// parentVar->text = nodeText; -// } else { -// PWatchVar newVar = std::make_shared(); -// newVar->parent = parentVar.get(); -// newVar->name = ""; -// newVar->text = nodeText; -// newVar->gdbIndex = -1; -// parentVar->children.append(newVar); -// } -// } -// } - // TODO: remember expansion state -} - void DebugReader::runNextCmd() { QMutexLocker locker(&mCmdQueueMutex); @@ -1100,10 +903,19 @@ void DebugReader::runNextCmd() emit cmdStarted(); QByteArray s; + QByteArray params; s=pCmd->command.toLocal8Bit(); if (!pCmd->params.isEmpty()) { - s+= ' '+pCmd->params.toLocal8Bit(); + params = pCmd->params.toLocal8Bit(); } + if (pCmd->command == "-var-create") { + //hack for variable creation,to easy remember var expression + params = " - @ "+params; + } else if (pCmd->command == "-var-list-children") { + //hack for list variable children,to easy remember var expression + params = " --all-values " + params; + } + s+=" "+params; s+= "\n"; if (mProcess->write(s)<0) { emit writeToDebugFailed(); @@ -1113,9 +925,9 @@ void DebugReader::runNextCmd() if (pSettings->debugger().enableDebugConsole() ) { //update debug console if (!pSettings->debugger().showDetailLog()) { - emit changeDebugConsoleLastLine(pCmd->command + ' ' + pCmd->params); + emit changeDebugConsoleLastLine(pCmd->command + ' ' + params); } else { - emit changeDebugConsoleLastLine(pCmd->command + ' ' + pCmd->params); + emit changeDebugConsoleLastLine(pCmd->command + ' ' + params); } } } @@ -1309,6 +1121,62 @@ void DebugReader::handleRegisterValue(const QList emit registerValuesUpdated(result); } +void DebugReader::handleCreateVar(const GDBMIResultParser::ParseObject &multiVars) +{ + if (!mCurrentCmd) + return; + QString expression = mCurrentCmd->params; + QString name = multiVars["name"].value(); + int numChild = multiVars["numchild"].intValue(0); + QString value = multiVars["value"].value(); + QString type = multiVars["type"].value(); + bool hasMore = multiVars["has_more"].value() != "0"; + emit varCreated(expression,name,numChild,value,type,hasMore); +} + +void DebugReader::handleListVarChildren(const GDBMIResultParser::ParseObject &multiVars) +{ + if (!mCurrentCmd) + return; + QString parentName = mCurrentCmd->params; + int parentNumChild = multiVars["numchild"].intValue(0); + QList children = multiVars["children"].array(); + bool hasMore = multiVars["has_more"].value()!="0"; + emit prepareVarChildren(parentName,parentNumChild,hasMore); + foreach(const GDBMIResultParser::ParseValue& child, children) { + GDBMIResultParser::ParseObject childObj = child.object(); + QString name = childObj["name"].value(); + QString exp = childObj["exp"].value(); + int numChild = childObj["numchild"].intValue(0); + QString value = childObj["value"].value(); + QString type = childObj["type"].value(); + bool hasMore = childObj["has_more"].value() != "0"; + emit addVarChild(parentName, + name, + exp, + numChild, + value, + type, + hasMore); + } +} + +void DebugReader::handleUpdateVarValue(const QList &changes) +{ + foreach (const GDBMIResultParser::ParseValue& value, changes) { + GDBMIResultParser::ParseObject obj = value.object(); + QString name = obj["name"].value(); + QString val = obj["value"].value(); + QString inScope = obj["in_scope"].value(); + bool typeChanged = (obj["type_changed"].value()=="true"); + QString newType = obj["new_type"].value(); + int newNumChildren = obj["new_num_children"].intValue(-1); + bool hasMore = (obj["has_more"].value() == "1"); + emit varValueUpdated(name,val,inScope,typeChanged,newType,newNumChildren, + hasMore); + } +} + QByteArray DebugReader::removeToken(const QByteArray &line) { int p=0; @@ -1374,16 +1242,6 @@ bool DebugReader::processExited() const return mProcessExited; } -bool DebugReader::invalidateAllVars() const -{ - return mInvalidateAllVars; -} - -void DebugReader::setInvalidateAllVars(bool invalidateAllVars) -{ - mInvalidateAllVars = invalidateAllVars; -} - QString DebugReader::debuggerPath() const { return mDebuggerPath; @@ -1810,7 +1668,6 @@ QVariant WatchModel::data(const QModelIndex &index, int role) const WatchVar* item = static_cast(index.internalPointer()); switch (role) { case Qt::DisplayRole: - //qDebug()<<"item->text:"<text; switch(index.column()) { case 0: return item->expression; @@ -1827,7 +1684,6 @@ QModelIndex WatchModel::index(int row, int column, const QModelIndex &parent) co { if (!hasIndex(row,column,parent)) return QModelIndex(); - WatchVar* parentItem; PWatchVar pChild; if (!parent.isValid()) { @@ -1897,9 +1753,9 @@ void WatchModel::addWatchVar(PWatchVar watchVar) return; } } - this->beginInsertRows(QModelIndex(),mWatchVars.size(),mWatchVars.size()); + beginInsertRows(QModelIndex(),mWatchVars.count(),mWatchVars.count()); mWatchVars.append(watchVar); - this->endInsertRows(); + endInsertRows(); } void WatchModel::removeWatchVar(const QString &express) @@ -1909,6 +1765,8 @@ void WatchModel::removeWatchVar(const QString &express) if (express == var->expression) { this->beginResetModel(); //this->beginRemoveRows(QModelIndex(),i,i); + if (mVarIndex.contains(var->name)) + mVarIndex.remove(var->name); mWatchVars.removeAt(i); //this->endRemoveRows(); this->endResetModel(); @@ -1920,6 +1778,9 @@ void WatchModel::removeWatchVar(const QModelIndex &index) { int r=index.row(); this->beginRemoveRows(QModelIndex(),r,r); + PWatchVar var = mWatchVars[r]; + if (mVarIndex.contains(var->name)) + mVarIndex.remove(var->name); mWatchVars.removeAt(r); this->endRemoveRows(); } @@ -1936,24 +1797,124 @@ const QList &WatchModel::watchVars() return mWatchVars; } -PWatchVar WatchModel::findWatchVar(const QString &name) +PWatchVar WatchModel::findWatchVar(const QModelIndex &index) +{ + if (!index.isValid()) + return PWatchVar(); + int r=index.row(); + return mWatchVars[r]; +} + +PWatchVar WatchModel::findWatchVar(const QString &expr) { for (PWatchVar var:mWatchVars) { - if (name == var->name) { + if (expr == var->expression) { return var; } } return PWatchVar(); } -PWatchVar WatchModel::findWatchVar(int gdbIndex) +void WatchModel::resetAllVarInfos() { - for (PWatchVar var:mWatchVars) { - if (gdbIndex == var->gdbIndex) { - return var; - } + beginResetModel(); + foreach (PWatchVar var, mWatchVars) { + var->name.clear(); + var->value = tr("Not Valid"); + var->numChild = 0; + var->hasMore = false; + var->type.clear(); + var->children.clear(); } - return PWatchVar(); + mVarIndex.clear(); + endResetModel(); +} + +void WatchModel::updateVarInfo(const QString &expression, const QString &name, int numChild, const QString &value, const QString &type, bool hasMore) +{ + PWatchVar var = findWatchVar(expression); + if (!var) + return; + var->name = name; + var->value = value; + var->numChild = numChild; + var->hasMore = hasMore; + var->type = type; + mVarIndex.insert(name,var); + QModelIndex idx = index(var); + if (!idx.isValid()) + return; + emit dataChanged(idx,createIndex(idx.row(),2,var.get())); +} + +void WatchModel::prepareVarChildren(const QString &parentName, int numChild, bool hasMore) +{ + PWatchVar var = mVarIndex.value(parentName,PWatchVar()); + if (var) { + var->numChild = numChild; + var->hasMore = hasMore; + } +} + +void WatchModel::addVarChild(const QString &parentName, const QString &name, + const QString &exp, int numChild, const QString &value, + const QString &type, bool hasMore) +{ + PWatchVar var = mVarIndex.value(parentName,PWatchVar()); + if (!var) + return; + beginInsertRows(index(var),var->children.count(),var->children.count()); + PWatchVar child = std::make_shared(); + child->name = name; + child->expression = exp; + child->numChild = numChild; + child->value = value; + child->type = type; + child->hasMore = hasMore; + child->parent = var.get(); + var->children.append(child); + endInsertRows(); + mVarIndex.insert(name,child); +} + +void WatchModel::updateVarValue(const QString &name, const QString &val, const QString &inScope, bool typeChanged, const QString &newType, int newNumChildren, bool hasMore) +{ + PWatchVar var = mVarIndex.value(name,PWatchVar()); + if (!var) + return; + if (inScope == "true") { + var->value = val; + } else{ + var->value = tr("Not Valid"); + } + if (typeChanged) { + var->type = newType; + } + QModelIndex idx = index(var); + if (newNumChildren>=0 + && var->numChild!=newNumChildren) { + beginRemoveRows(idx,0,var->children.count()); + var->children.clear(); + endRemoveRows(); + var->numChild = newNumChildren; + } + var->hasMore = hasMore; + emit dataChanged(idx,createIndex(idx.row(),2,var.get())); +} + +void WatchModel::clearAllVarInfos() +{ + beginResetModel(); + foreach (PWatchVar var, mWatchVars) { + var->name.clear(); + var->value = tr("Execute to evaluate"); + var->numChild = 0; + var->hasMore = false; + var->type.clear(); + var->children.clear(); + } + mVarIndex.clear(); + endResetModel(); } void WatchModel::beginUpdate() @@ -2036,6 +1997,7 @@ void WatchModel::load(const QString &filename) var->value = tr("Execute to evaluate"); var->numChild = 0; var->hasMore=false; + var->parent = nullptr; addWatchVar(var); } @@ -2045,6 +2007,41 @@ void WatchModel::load(const QString &filename) } } +QModelIndex WatchModel::index(PWatchVar var) const +{ + if (!var) + return QModelIndex(); + return index(var.get()); +} + +QModelIndex WatchModel::index(WatchVar* pVar) const { + if (pVar==nullptr) + return QModelIndex(); + if (pVar->parent) { + int row=-1; + for (int i=0;iparent->children.count();i++) { + if (pVar->parent->children[i].get() == pVar) { + row = i; + break; + } + } + if (row<0) + return QModelIndex(); + return createIndex(row,0,pVar); + } else { + int row=-1; + for (int i=0;i(parent.internalPointer()); + item->hasMore = false; + item->numChild = item->children.count(); + emit fetchChildren(item->name); } bool WatchModel::canFetchMore(const QModelIndex &parent) const @@ -2072,13 +2075,13 @@ bool WatchModel::canFetchMore(const QModelIndex &parent) const return false; } WatchVar* item = static_cast(parent.internalPointer()); - return item->numChild>item->children.count(); + return item->numChild>item->children.count() || item->hasMore; } bool WatchModel::hasChildren(const QModelIndex &parent) const { if (!parent.isValid()) { - return false; + return true; } WatchVar* item = static_cast(parent.internalPointer()); return item->numChild>0; diff --git a/RedPandaIDE/debugger.h b/RedPandaIDE/debugger.h index 345a6093..f08ce6e0 100644 --- a/RedPandaIDE/debugger.h +++ b/RedPandaIDE/debugger.h @@ -131,34 +131,51 @@ public: QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; QModelIndex parent(const QModelIndex &index) const override; - + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + void fetchMore(const QModelIndex &parent) override; + bool canFetchMore(const QModelIndex &parent) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; + bool hasChildren(const QModelIndex &parent) const override; void addWatchVar(PWatchVar watchVar); void removeWatchVar(const QString& expression); void removeWatchVar(const QModelIndex& index); void clear(); const QList& watchVars(); - PWatchVar findWatchVar(const QString& name); - PWatchVar findWatchVar(int gdbIndex); + PWatchVar findWatchVar(const QModelIndex& index); + PWatchVar findWatchVar(const QString& expr); + void resetAllVarInfos(); + void clearAllVarInfos(); void beginUpdate(); void endUpdate(); void notifyUpdated(PWatchVar var); void save(const QString& filename); void load(const QString& filename); +public slots: + void updateVarInfo(const QString& expression, + const QString& name, + int numChild, + const QString& value, + const QString& type, + bool hasMore); + void prepareVarChildren(const QString& parentName, int numChild, bool hasMore); + void addVarChild(const QString& parentName, const QString& name, + const QString& exp, int numChild, + const QString& value, const QString& type, + bool hasMore); + void updateVarValue(const QString& name, const QString& val, + const QString& inScope, bool typeChanged, + const QString& newType, int newNumChildren, + bool hasMore); +signals: + void fetchChildren(const QString& name); +private: + QModelIndex index(PWatchVar var) const; + QModelIndex index(WatchVar* pVar) const; private: QList mWatchVars; + QHash mVarIndex; int mUpdateCount; - - // QAbstractItemModel interface -public: - QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - void fetchMore(const QModelIndex &parent); - bool canFetchMore(const QModelIndex &parent) const; - - // QAbstractItemModel interface -public: - bool hasChildren(const QModelIndex &parent) const; }; @@ -192,25 +209,16 @@ public: PBreakpoint breakpointAt(int line, const Editor* editor, int &index); void setBreakPointCondition(int index, const QString& condition); void sendAllBreakpointsToDebugger(); - void validateBreakpoint(int line, const QString& filename, int number); - void invalidateAllBreakpoints(); //watch vars - void addWatchVar(const QString& namein); -// void removeWatchVar(nodein: TTreeNode); overload; - void renameWatchVar(const QString& oldname, const QString& newname); + void addWatchVar(const QString& expression); + void modifyWatchVarExpression(const QString& oldExpr, const QString& newExpr); - void refreshWatchVars(); void removeWatchVars(bool deleteparent); void removeWatchVar(const QModelIndex& index); - void invalidateAllVars(); - void sendAllWatchvarsToDebugger(); - void invalidateWatchVar(const QString& name); - void invalidateWatchVar(PWatchVar var); - PWatchVar findWatchVar(const QString& name); + void sendAllWatchVarsToDebugger(); + PWatchVar findWatchVar(const QString& expression); // void notifyWatchVarUpdated(PWatchVar var); - void notifyBeforeProcessWatchVar(); - void notifyAfterProcessWatchVar(); BacktraceModel* backtraceModel(); BreakpointModel* breakpointModel(); @@ -246,7 +254,8 @@ private slots: void clearUpReader(); void updateRegisterNames(const QStringList& registerNames); void updateRegisterValues(const QHash& values); - + void refreshWatchVars(); + void fetchVarChildren(const QString& varName); private: bool mExecuting; bool mCommandChanged; @@ -272,9 +281,6 @@ public: bool commandRunning(); void waitStart(); - bool invalidateAllVars() const; - void setInvalidateAllVars(bool invalidateAllVars); - bool inferiorPaused() const; bool processExited() const; @@ -332,11 +338,24 @@ signals: void disassemblyUpdate(const QString& filename, const QString& funcName, const QStringList& result); void registerNamesUpdated(const QStringList& registerNames); void registerValuesUpdated(const QHash& values); + void varCreated(const QString& expression, + const QString& name, + int numChild, + const QString& value, + const QString& type, + bool hasMore); + void prepareVarChildren(const QString& parentName,int numChild, bool hasMore); + void addVarChild(const QString& parentName, const QString& name, + const QString& exp, int numChild, + const QString& value, const QString& type, + bool hasMore); + void varValueUpdated(const QString& name, const QString& val, + const QString& inScope, bool typeChanged, + const QString& newType, int newNumChildren, + bool hasMore); private: void clearCmdQueue(); - QString processEvalOutput(); - void processWatchOutput(PWatchVar WatchVar); void runNextCmd(); QStringList tokenize(const QString& s); @@ -348,6 +367,9 @@ private: void handleMemory(const QList & rows); void handleRegisterNames(const QList & names); void handleRegisterValue(const QList & values); + void handleCreateVar(const GDBMIResultParser::ParseObject& multiVars); + void handleListVarChildren(const GDBMIResultParser::ParseObject& multiVars); + void handleUpdateVarValue(const QList &changes); void processConsoleOutput(const QByteArray& line); void processResult(const QByteArray& result); void processExecAsyncRecord(const QByteArray& line); @@ -362,7 +384,6 @@ private: QRecursiveMutex mCmdQueueMutex; QSemaphore mStartSemaphore; QQueue mCmdQueue; - bool mInvalidateAllVars; //fOnInvalidateAllVars: TInvalidateAllVarsEvent; bool mCmdRunning; diff --git a/RedPandaIDE/gdbmiresultparser.cpp b/RedPandaIDE/gdbmiresultparser.cpp index 961da48a..d6767850 100644 --- a/RedPandaIDE/gdbmiresultparser.cpp +++ b/RedPandaIDE/gdbmiresultparser.cpp @@ -18,6 +18,9 @@ GDBMIResultParser::GDBMIResultParser() mResultTypes.insert("-data-read-memory",GDBMIResultType::Memory); mResultTypes.insert("-data-list-register-names",GDBMIResultType::RegisterNames); mResultTypes.insert("-data-list-register-values",GDBMIResultType::RegisterValues); + mResultTypes.insert("-var-create",GDBMIResultType::CreateVar); + mResultTypes.insert("-var-list-children",GDBMIResultType::ListVarChildren); + mResultTypes.insert("-var-update",GDBMIResultType::UpdateVarValue); } bool GDBMIResultParser::parse(const QByteArray &record, const QString& command, GDBMIResultType &type, ParseObject& multiValues) @@ -290,6 +293,8 @@ bool GDBMIResultParser::isNameChar(char ch) { if (ch=='-') return true; + if (ch=='_') + return true; if (ch>='a' && ch<='z') return true; if (ch>='A' && ch<='Z') @@ -315,19 +320,16 @@ void GDBMIResultParser::skipSpaces(const char *&p) const QByteArray &GDBMIResultParser::ParseValue::value() const { - Q_ASSERT(mType == ParseValueType::Value); return mValue; } const QList<::GDBMIResultParser::ParseValue> &GDBMIResultParser::ParseValue::array() const { - Q_ASSERT(mType == ParseValueType::Array); return mArray; } const GDBMIResultParser::ParseObject &GDBMIResultParser::ParseValue::object() const { - Q_ASSERT(mType == ParseValueType::Object); return mObject; } diff --git a/RedPandaIDE/gdbmiresultparser.h b/RedPandaIDE/gdbmiresultparser.h index 4b0964b8..c7742612 100644 --- a/RedPandaIDE/gdbmiresultparser.h +++ b/RedPandaIDE/gdbmiresultparser.h @@ -19,8 +19,9 @@ enum class GDBMIResultType { RegisterNames, RegisterValues, Memory, - VariableInfo, - + CreateVar, + ListVarChildren, + UpdateVarValue }; diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 7aa2184e..fb3c2d1b 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -1444,10 +1444,6 @@ void MainWindow::debug() includeOrSkipDirs(compilerSet->defaultCppIncludeDirs(),true); } - // Add breakpoints and watch vars -// for i := 0 to fDebugger.WatchVarList.Count - 1 do -// fDebugger.AddWatchVar(i); - mDebugger->sendAllWatchvarsToDebugger(); mDebugger->sendAllBreakpointsToDebugger(); // Run the debugger @@ -1677,10 +1673,10 @@ void MainWindow::includeOrSkipDirs(const QStringList &dirs, bool skip) foreach (QString dir,dirs) { QString dirName = dir.replace('\\','/'); if (skip) { -// mDebugger->sendCommand( -// "skip", -// QString("-gfi \"%1/%2\"") -// .arg(dirName,"*.*")); + mDebugger->sendCommand( + "skip", + QString("-gfi \"%1/%2\"") + .arg(dirName,"*.*")); } else { mDebugger->sendCommand( "-environment-directory", @@ -4001,7 +3997,6 @@ void MainWindow::on_actionStep_Over_triggered() { if (mDebugger->executing()) { //WatchView.Items.BeginUpdate(); - mDebugger->invalidateAllVars(); mDebugger->sendCommand("-exec-next", ""); } } @@ -4010,7 +4005,6 @@ void MainWindow::on_actionStep_Into_triggered() { if (mDebugger->executing()) { //WatchView.Items.BeginUpdate(); - mDebugger->invalidateAllVars(); mDebugger->sendCommand("-exec-step", ""); } @@ -4020,7 +4014,6 @@ void MainWindow::on_actionStep_Out_triggered() { if (mDebugger->executing()) { //WatchView.Items.BeginUpdate(); - mDebugger->invalidateAllVars(); mDebugger->sendCommand("-exec-finish", ""); } @@ -4032,7 +4025,6 @@ void MainWindow::on_actionRun_To_Cursor_triggered() Editor *e=mEditorList->getEditor(); if (e!=nullptr) { //WatchView.Items.BeginUpdate(); - mDebugger->invalidateAllVars(); mDebugger->sendCommand("-exec-until", QString("\"%1\":%2") .arg(e->filename()) .arg(e->caretY())); @@ -4045,7 +4037,6 @@ void MainWindow::on_actionContinue_triggered() { if (mDebugger->executing()) { //WatchView.Items.BeginUpdate(); - mDebugger->invalidateAllVars(); mDebugger->sendCommand("-exec-continue", ""); } } diff --git a/RedPandaIDE/mainwindow.ui b/RedPandaIDE/mainwindow.ui index e9d75868..bcef089b 100644 --- a/RedPandaIDE/mainwindow.ui +++ b/RedPandaIDE/mainwindow.ui @@ -85,7 +85,7 @@ QTabWidget::West - 3 + 1 true @@ -174,7 +174,7 @@ false - 50 + 100 diff --git a/RedPandaIDE/version.h b/RedPandaIDE/version.h index e80b2153..e8f5a828 100644 --- a/RedPandaIDE/version.h +++ b/RedPandaIDE/version.h @@ -2,6 +2,6 @@ #define VERSION_H #include -#define DEVCPP_VERSION "beta.0.9.3" +#define DEVCPP_VERSION "beta.0.10.0" #endif // VERSION_H From da27fba8f1bb1d7e344676687f2e95a1bc606843 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Thu, 25 Nov 2021 20:50:51 +0800 Subject: [PATCH 23/32] - fix: project's modified flag not cleared after saved --- NEWS.md | 1 + RedPandaIDE/project.cpp | 8 +++----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/NEWS.md b/NEWS.md index 9fce4961..7bd55e18 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,7 @@ Version 0.10.0 For Dev-C++ 7 Beta - enhancement: use gdb/mi interface to communicate with gdb debug session - enhancement: better display of watch vars + - fix: project's modified flag not cleared after saved Version 0.9.3 For Dev-C++ 7 Beta - fix: the count in the title of issues view isn't correct diff --git a/RedPandaIDE/project.cpp b/RedPandaIDE/project.cpp index 021f2ba3..3257e6c9 100644 --- a/RedPandaIDE/project.cpp +++ b/RedPandaIDE/project.cpp @@ -107,8 +107,9 @@ bool Project::modified() const // Otherwise, check all units foreach (const PProjectUnit& unit, mUnits){ - if (unit->modified()) + if (unit->modified()) { return true; + } } return false; } @@ -184,10 +185,7 @@ void Project::setFileName(QString value) void Project::setModified(bool value) { - QFile file(mFilename); - // only mark modified if *not* read-only - if (!file.exists() - || (file.exists() && file.isWritable())) { + if (mModified!=value) { mModified=value; emit modifyChanged(mModified); } From 817b1ca11f7b568042ea894e1547aa3e2fc482b0 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Thu, 25 Nov 2021 20:52:52 +0800 Subject: [PATCH 24/32] update NEWS.md --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index 7bd55e18..94148481 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,6 +3,9 @@ Version 0.10.0 For Dev-C++ 7 Beta - enhancement: better display of watch vars - fix: project's modified flag not cleared after saved +Version 0.9.4 For Dev-C++ 7 Beta + - fix: code formatter's "indent type" option not correctly saved + Version 0.9.3 For Dev-C++ 7 Beta - fix: the count in the title of issues view isn't correct - fix: columns calculation not correct when paint lines containing chinese characters From cbec8f60f4ef0e3fda427e895e1e6a0e48b55db6 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Thu, 25 Nov 2021 21:44:08 +0800 Subject: [PATCH 25/32] - fix: can't correctly display stl containers in watch --- NEWS.md | 4 ++++ RedPandaIDE/debugger.cpp | 16 +++++++++++----- RedPandaIDE/mainwindow.cpp | 1 + RedPandaIDE/version.h | 2 +- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/NEWS.md b/NEWS.md index 94148481..a215f6d8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +Version 0.10.1 For Dev-C++ 7 Beta + - fix: can't correctly expand watch expression that has spaces in it + - fix: can't correctly display stl containers in watch + Version 0.10.0 For Dev-C++ 7 Beta - enhancement: use gdb/mi interface to communicate with gdb debug session - enhancement: better display of watch vars diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index 06f6ae10..d8f51560 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -913,7 +913,7 @@ void DebugReader::runNextCmd() params = " - @ "+params; } else if (pCmd->command == "-var-list-children") { //hack for list variable children,to easy remember var expression - params = " --all-values " + params; + params = " --all-values \"" + params+'\"'; } s+=" "+params; s+= "\n"; @@ -1853,6 +1853,11 @@ void WatchModel::prepareVarChildren(const QString &parentName, int numChild, boo if (var) { var->numChild = numChild; var->hasMore = hasMore; + if (var->children.count()>0) { + beginRemoveRows(index(var),0,var->children.count()-1); + var->children.clear(); + endRemoveRows(); + } } } @@ -1891,14 +1896,15 @@ void WatchModel::updateVarValue(const QString &name, const QString &val, const Q var->type = newType; } QModelIndex idx = index(var); + bool oldHasMore = var->hasMore; + var->hasMore = hasMore; if (newNumChildren>=0 && var->numChild!=newNumChildren) { - beginRemoveRows(idx,0,var->children.count()); - var->children.clear(); - endRemoveRows(); var->numChild = newNumChildren; + fetchMore(idx); + } else if (!oldHasMore && hasMore) { + fetchMore(idx); } - var->hasMore = hasMore; emit dataChanged(idx,createIndex(idx.row(),2,var.get())); } diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index fb3c2d1b..82183287 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -1447,6 +1447,7 @@ void MainWindow::debug() mDebugger->sendAllBreakpointsToDebugger(); // Run the debugger + mDebugger->sendCommand("-enable-pretty-printing",""); mDebugger->sendCommand("-data-list-register-names",""); mDebugger->sendCommand("-gdb-set", "width 0"); // don't wrap output, very annoying mDebugger->sendCommand("-gdb-set", "new-console on"); diff --git a/RedPandaIDE/version.h b/RedPandaIDE/version.h index e8f5a828..5285c2e7 100644 --- a/RedPandaIDE/version.h +++ b/RedPandaIDE/version.h @@ -2,6 +2,6 @@ #define VERSION_H #include -#define DEVCPP_VERSION "beta.0.10.0" +#define DEVCPP_VERSION "beta.0.10.1" #endif // VERSION_H From 2fffe33bb7a31dd783f5463a3a2aefd2cc02580d Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Thu, 25 Nov 2021 23:41:40 +0800 Subject: [PATCH 26/32] - fix: the last line in the debug console is not correctly displayed --- NEWS.md | 1 + RedPandaIDE/debugger.cpp | 24 +++++++++++++++++------- RedPandaIDE/mainwindow.cpp | 4 +++- RedPandaIDE/widgets/qconsole.cpp | 2 +- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/NEWS.md b/NEWS.md index a215f6d8..31e757f0 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,7 @@ Version 0.10.1 For Dev-C++ 7 Beta - fix: can't correctly expand watch expression that has spaces in it - fix: can't correctly display stl containers in watch + - fix: the last line in the debug console is not correctly displayed Version 0.10.0 For Dev-C++ 7 Beta - enhancement: use gdb/mi interface to communicate with gdb debug session diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index d8f51560..f4018667 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -467,8 +467,18 @@ void Debugger::syncFinishedParsing() pMainWindow->addDebugOutput(line); } } else { - for (const QString& line:mReader->consoleOutput()) { - pMainWindow->addDebugOutput(line); + if (mReader->currentCmd() && mReader->currentCmd()->command == "disas") { + + } else { + for (const QString& line:mReader->consoleOutput()) { + pMainWindow->addDebugOutput(line); + } + if ( + (mReader->currentCmd() + && mReader->currentCmd()->source== DebugCommandSource::Console) + || !mReader->consoleOutput().isEmpty() ) { + pMainWindow->addDebugOutput("(gdb)"); + } } } } @@ -851,7 +861,8 @@ void DebugReader::processDebugOutput(const QByteArray& debugOutput) for (int i=0;idebugger().showDetailLog()) + mFullOutput.append(line); line = removeToken(line); if (line.isEmpty()) { continue; @@ -924,9 +935,8 @@ void DebugReader::runNextCmd() // if devDebugger.ShowCommandLog or pCmd^.ShowInConsole then begin if (pSettings->debugger().enableDebugConsole() ) { //update debug console - if (!pSettings->debugger().showDetailLog()) { - emit changeDebugConsoleLastLine(pCmd->command + ' ' + params); - } else { + if (pSettings->debugger().showDetailLog() + && pCmd->source != DebugCommandSource::Console) { emit changeDebugConsoleLastLine(pCmd->command + ' ' + params); } } @@ -1333,7 +1343,7 @@ void DebugReader::run() } else if (!mCmdRunning && readed.isEmpty()){ runNextCmd(); } else if (readed.isEmpty()){ - msleep(100); + msleep(1); } } if (errorOccurred) { diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 82183287..f7fab347 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -741,6 +741,8 @@ void MainWindow::updateAppTitle() void MainWindow::addDebugOutput(const QString &text) { + if (!pSettings->debugger().enableDebugConsole()) + return; if (text.isEmpty()) { ui->debugConsole->addLine(""); } else { @@ -1572,7 +1574,7 @@ void MainWindow::prepareDebugger() // Clear logs ui->debugConsole->clear(); - if (!pSettings->debugger().enableDebugConsole()) { + if (pSettings->debugger().enableDebugConsole()) { ui->debugConsole->addLine("(gdb) "); } ui->txtEvalOutput->clear(); diff --git a/RedPandaIDE/widgets/qconsole.cpp b/RedPandaIDE/widgets/qconsole.cpp index e1d06ffa..97a0210a 100644 --- a/RedPandaIDE/widgets/qconsole.cpp +++ b/RedPandaIDE/widgets/qconsole.cpp @@ -276,7 +276,7 @@ void QConsole::setTopRow(int value) int QConsole::maxScrollHeight() { - return std::max(mContents.rows()-mRowsInWindow,1); + return std::max(mContents.rows()-mRowsInWindow+1,1); } void QConsole::updateScrollbars() From 03ae21ebf6057772caf0db8961dddb97bf615738 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Fri, 26 Nov 2021 08:14:23 +0800 Subject: [PATCH 27/32] - enhancement: scroll while dragging text in the editor --- NEWS.md | 1 + RedPandaIDE/qsynedit/SynEdit.cpp | 46 +++++++++++++++++++++++--------- RedPandaIDE/qsynedit/SynEdit.h | 1 + RedPandaIDE/widgets/qconsole.cpp | 6 ++--- 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/NEWS.md b/NEWS.md index 31e757f0..88b831da 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,6 +2,7 @@ Version 0.10.1 For Dev-C++ 7 Beta - fix: can't correctly expand watch expression that has spaces in it - fix: can't correctly display stl containers in watch - fix: the last line in the debug console is not correctly displayed + - enhancement: scroll while dragging text in the editor Version 0.10.0 For Dev-C++ 7 Beta - enhancement: use gdb/mi interface to communicate with gdb debug session diff --git a/RedPandaIDE/qsynedit/SynEdit.cpp b/RedPandaIDE/qsynedit/SynEdit.cpp index 2420b0f5..b27f86c8 100644 --- a/RedPandaIDE/qsynedit/SynEdit.cpp +++ b/RedPandaIDE/qsynedit/SynEdit.cpp @@ -34,6 +34,7 @@ SynEdit::SynEdit(QWidget *parent) : QAbstractScrollArea(parent) mOrigLines = mLines; //fPlugins := TList.Create; mMouseMoved = false; + mDragging = false; mUndoing = false; mLines->connect(mLines.get(), &SynEditStringList::changed, this, &SynEdit::onLinesChanged); mLines->connect(mLines.get(), &SynEditStringList::changing, this, &SynEdit::onLinesChanging); @@ -2483,14 +2484,16 @@ void SynEdit::computeCaret(int X, int Y) void SynEdit::computeScroll(int X, int Y) { QRect iScrollBounds; // relative to the client area - // don't scroll if dragging text from other control -// if (not MouseCapture) and (not Dragging) then begin -// fScrollTimer.Enabled := False; -// Exit; -// end; + int dispX,dispY = 2; + if (mDragging) { + dispX = mCharWidth / 2 -1; + dispY = mTextHeight/ 2 -1; + } - iScrollBounds = QRect(mGutterWidth+this->frameWidth(), this->frameWidth(), mCharsInWindow * mCharWidth, - mLinesInWindow * mTextHeight); + iScrollBounds = QRect(mGutterWidth+frameWidth()+dispX, + frameWidth()+dispY, + mCharsInWindow * mCharWidth-2*dispX, + mLinesInWindow * mTextHeight-2*dispY); if (X < iScrollBounds.left()) mScrollDeltaX = (X - iScrollBounds.left()) / mCharWidth - 1; @@ -5948,7 +5951,7 @@ void SynEdit::mousePressEvent(QMouseEvent *event) // setBlockBegin(TmpBegin); // setBlockEnd(TmpEnd); - setMouseTracking(true); + //setMouseTracking(true); //if mousedown occurred in selected block begin drag operation mStateFlags.setFlag(SynStateFlag::sfWaitForDragging,false); if (bWasSel && mOptions.testFlag(eoDragDropEditing) && (X >= mGutterWidth + 2) @@ -5988,7 +5991,7 @@ void SynEdit::mouseReleaseEvent(QMouseEvent *event) mScrollTimer->stop(); // if ((button = ) and (Shift = [ssRight]) and Assigned(PopupMenu) then // exit; - setMouseTracking(false); + //setMouseTracking(false); if (mStateFlags.testFlag(SynStateFlag::sfWaitForDragging) && !mStateFlags.testFlag(SynStateFlag::sfDblClicked)) { @@ -6129,6 +6132,7 @@ QVariant SynEdit::inputMethodQuery(Qt::InputMethodQuery property) const void SynEdit::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasFormat("text/plain")) { + mDragging = true; event->acceptProposedAction(); mDragCaretSave = caretXY(); mDragSelBeginSave = blockBegin(); @@ -6158,6 +6162,7 @@ void SynEdit::dropEvent(QDropEvent *event) setCaretXY(coord); setSelText(event->mimeData()->text()); event->acceptProposedAction(); + mDragging = false; } void SynEdit::dragMoveEvent(QDragMoveEvent *event) @@ -6167,9 +6172,21 @@ void SynEdit::dragMoveEvent(QDragMoveEvent *event) } else { event->setDropAction(Qt::MoveAction); } + // should we begin scrolling? + computeScroll(event->pos().x(), + event->pos().y()); +// DisplayCoord P = pixelsToNearestRowColumn(X, Y); +// P.Row = minMax(P.Row, 1, displayLineCount()); +// if (mScrollDeltaX != 0) +// P.Column = displayX(); +// if (mScrollDeltaY != 0) +// P.Row = displayY(); +// internalSetCaretXY(displayToBufferPos(P)); +// setBlockEnd(caretXY()); + BufferCoord coord = displayToBufferPos(pixelsToNearestRowColumn(event->pos().x(), event->pos().y())); - setCaretXY(coord); + internalSetCaretXY(coord); setBlockBegin(mDragSelBeginSave); setBlockEnd(mDragSelEndSave); showCaret(); @@ -6181,6 +6198,8 @@ void SynEdit::dragLeaveEvent(QDragLeaveEvent *) setBlockBegin(mDragSelBeginSave); setBlockEnd(mDragSelEndSave); showCaret(); + mScrollTimer->stop(); + mDragging = false; } int SynEdit::maxScrollHeight() const @@ -6591,8 +6610,11 @@ void SynEdit::onScrollTimeout() internalSetCaretXY(vCaret); // if MouseCapture is True we're changing selection. otherwise we're dragging -// if (mouseCapture()) - setBlockEnd(caretXY()); + if (mDragging) { + setBlockBegin(mDragSelBeginSave); + setBlockEnd(mDragSelEndSave); + } else + setBlockEnd(caretXY()); } computeScroll(iMousePos.x(), iMousePos.y()); } diff --git a/RedPandaIDE/qsynedit/SynEdit.h b/RedPandaIDE/qsynedit/SynEdit.h index 596bdc63..d5fcc091 100644 --- a/RedPandaIDE/qsynedit/SynEdit.h +++ b/RedPandaIDE/qsynedit/SynEdit.h @@ -701,6 +701,7 @@ private: BufferCoord mDragCaretSave; BufferCoord mDragSelBeginSave; BufferCoord mDragSelEndSave; + bool mDragging; friend class SynEditTextPainter; diff --git a/RedPandaIDE/widgets/qconsole.cpp b/RedPandaIDE/widgets/qconsole.cpp index 97a0210a..2697f339 100644 --- a/RedPandaIDE/widgets/qconsole.cpp +++ b/RedPandaIDE/widgets/qconsole.cpp @@ -43,7 +43,7 @@ QConsole::QConsole(QWidget *parent): mBlinkStatus = 0; //enable input method setAttribute(Qt::WA_InputMethodEnabled); - setMouseTracking(false); +// setMouseTracking(false); recalcCharExtent(); mScrollTimer = new QTimer(this); mScrollTimer->setInterval(100); @@ -504,7 +504,7 @@ void QConsole::mousePressEvent(QMouseEvent *event) //fKbdHandler.ExecuteMouseDown(Self, Button, Shift, X, Y); if (button == Qt::LeftButton) { - setMouseTracking(true); +// setMouseTracking(true); RowColumn mousePosRC = pixelsToNearestRowColumn(X,Y); LineChar mousePos = mContents.rowColumnToLineChar(mousePosRC); //I couldn't track down why, but sometimes (and definitely not all the time) @@ -522,7 +522,7 @@ void QConsole::mouseReleaseEvent(QMouseEvent *event) { QAbstractScrollArea::mouseReleaseEvent(event); mScrollTimer->stop(); - setMouseTracking(false); +// setMouseTracking(false); } From f8a8f5df67b592c2585cedd6502d6b5cd528ba30 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Fri, 26 Nov 2021 08:29:00 +0800 Subject: [PATCH 28/32] - fix: dragging out of the editor shouldn't reset the caret back --- NEWS.md | 1 + RedPandaIDE/qsynedit/SynEdit.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/NEWS.md b/NEWS.md index 88b831da..24099e43 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,6 +3,7 @@ Version 0.10.1 For Dev-C++ 7 Beta - fix: can't correctly display stl containers in watch - fix: the last line in the debug console is not correctly displayed - enhancement: scroll while dragging text in the editor + - fix: dragging out of the editor shouldn't reset the caret back Version 0.10.0 For Dev-C++ 7 Beta - enhancement: use gdb/mi interface to communicate with gdb debug session diff --git a/RedPandaIDE/qsynedit/SynEdit.cpp b/RedPandaIDE/qsynedit/SynEdit.cpp index b27f86c8..4f50f7ff 100644 --- a/RedPandaIDE/qsynedit/SynEdit.cpp +++ b/RedPandaIDE/qsynedit/SynEdit.cpp @@ -6194,10 +6194,10 @@ void SynEdit::dragMoveEvent(QDragMoveEvent *event) void SynEdit::dragLeaveEvent(QDragLeaveEvent *) { - setCaretXY(mDragCaretSave); - setBlockBegin(mDragSelBeginSave); - setBlockEnd(mDragSelEndSave); - showCaret(); +// setCaretXY(mDragCaretSave); +// setBlockBegin(mDragSelBeginSave); +// setBlockEnd(mDragSelEndSave); +// showCaret(); mScrollTimer->stop(); mDragging = false; } From ed3f320c50321cecf727c3d99fe3ce9bf08500c4 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Fri, 26 Nov 2021 19:04:04 +0800 Subject: [PATCH 29/32] - fix: select by mouse can't correctly set mouse's column position - fix: dragging out of the editor and back will cause error --- NEWS.md | 4 + RedPandaIDE/qsynedit/SynEdit.cpp | 195 ++++++++++++++++--------------- RedPandaIDE/qsynedit/SynEdit.h | 5 +- 3 files changed, 111 insertions(+), 93 deletions(-) diff --git a/NEWS.md b/NEWS.md index 24099e43..0f3c1bbc 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +Version 0.10.2 For Dev-C++ 7 Beta + - fix: select by mouse can't correctly set mouse's column position + - fix: dragging out of the editor and back will cause error + Version 0.10.1 For Dev-C++ 7 Beta - fix: can't correctly expand watch expression that has spaces in it - fix: can't correctly display stl containers in watch diff --git a/RedPandaIDE/qsynedit/SynEdit.cpp b/RedPandaIDE/qsynedit/SynEdit.cpp index 4f50f7ff..201874c0 100644 --- a/RedPandaIDE/qsynedit/SynEdit.cpp +++ b/RedPandaIDE/qsynedit/SynEdit.cpp @@ -34,7 +34,6 @@ SynEdit::SynEdit(QWidget *parent) : QAbstractScrollArea(parent) mOrigLines = mLines; //fPlugins := TList.Create; mMouseMoved = false; - mDragging = false; mUndoing = false; mLines->connect(mLines.get(), &SynEditStringList::changed, this, &SynEdit::onLinesChanged); mLines->connect(mLines.get(), &SynEditStringList::changing, this, &SynEdit::onLinesChanging); @@ -124,7 +123,7 @@ SynEdit::SynEdit(QWidget *parent) : QAbstractScrollArea(parent) | eoHideShowScrollbars ; mScrollTimer = new QTimer(this); - mScrollTimer->setInterval(100); + //mScrollTimer->setInterval(100); connect(mScrollTimer, &QTimer::timeout,this, &SynEdit::onScrollTimeout); mScrollHintColor = QColorConstants::Yellow; @@ -667,9 +666,9 @@ DisplayCoord SynEdit::pixelsToNearestRowColumn(int aX, int aY) const // don't return a partially visible last line if (aY >= mLinesInWindow * mTextHeight) { aY = mLinesInWindow * mTextHeight - 1; - if (aY < 0) - aY = 0; } + if (aY < 0) + aY = 0; return { std::max(1, (int)(leftChar() + round(f))), std::max(1, mTopLine + (aY / mTextHeight)) @@ -1764,6 +1763,52 @@ void SynEdit::doToggleComment() doComment(); } +void SynEdit::doMouseScroll(bool isDragging) +{ + QPoint iMousePos; + DisplayCoord C; + int X, Y; + + iMousePos = QCursor::pos(); + iMousePos = mapFromGlobal(iMousePos); + C = pixelsToRowColumn(iMousePos.x(), iMousePos.y()); + C.Row = minMax(C.Row, 1, displayLineCount()); + if (mScrollDeltaX != 0) { + setLeftChar(leftChar() + mScrollDeltaX); + X = leftChar(); + if (mScrollDeltaX > 0) // scrolling right? + X+=charsInWindow(); + C.Column = X; + } + if (mScrollDeltaY != 0) { + if (QApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier)) + setTopLine(mTopLine + mScrollDeltaY * mLinesInWindow); + else + setTopLine(mTopLine + mScrollDeltaY); + Y = mTopLine; + if (mScrollDeltaY > 0) // scrolling down? + Y+=mLinesInWindow - 1; + C.Row = minMax(Y, 1, displayLineCount()); + } + BufferCoord vCaret = displayToBufferPos(C); + if ((caretX() != vCaret.Char) || (caretY() != vCaret.Line)) { + // changes to line / column in one go + incPaintLock(); + auto action = finally([this]{ + decPaintLock(); + }); + internalSetCaretXY(vCaret); + + // if MouseCapture is True we're changing selection. otherwise we're dragging + if (isDragging) { + setBlockBegin(mDragSelBeginSave); + setBlockEnd(mDragSelEndSave); + } else + setBlockEnd(caretXY()); + } + computeScroll(iMousePos.x(), iMousePos.y(),isDragging); +} + void SynEdit::doDeleteLastChar() { if (mReadOnly) @@ -2481,19 +2526,25 @@ void SynEdit::computeCaret(int X, int Y) setInternalDisplayXY(vCaretNearestPos); } -void SynEdit::computeScroll(int X, int Y) +void SynEdit::computeScroll(int X, int Y, bool isDragging) { + if (!isDragging) { + Qt::MouseButtons buttons = qApp->mouseButtons(); + if (!buttons.testFlag(Qt::LeftButton)) + return; + } QRect iScrollBounds; // relative to the client area - int dispX,dispY = 2; - if (mDragging) { + int dispX=2,dispY = 2; + if (isDragging) { dispX = mCharWidth / 2 -1; dispY = mTextHeight/ 2 -1; } - - iScrollBounds = QRect(mGutterWidth+frameWidth()+dispX, - frameWidth()+dispY, - mCharsInWindow * mCharWidth-2*dispX, - mLinesInWindow * mTextHeight-2*dispY); + int left = mGutterWidth+frameWidth()+dispX; + int top = frameWidth()+dispY; + iScrollBounds = QRect(left, + top, + clientWidth()-left-dispX, + clientHeight()-top-dispY); if (X < iScrollBounds.left()) mScrollDeltaX = (X - iScrollBounds.left()) / mCharWidth - 1; @@ -2502,6 +2553,10 @@ void SynEdit::computeScroll(int X, int Y) else mScrollDeltaX = 0; + if (isDragging && (X<0 || X>clientRect().width())) { + mScrollDeltaX = 0; + } + if (Y < iScrollBounds.top()) mScrollDeltaY = (Y - iScrollBounds.top()) / mTextHeight - 1; else if (Y >= iScrollBounds.bottom()) @@ -2509,8 +2564,17 @@ void SynEdit::computeScroll(int X, int Y) else mScrollDeltaY = 0; - if (mScrollDeltaX!=0 || mScrollDeltaY!=0) - mScrollTimer->start(); + if (isDragging && (Y<0 || Y>clientRect().height())) { + mScrollDeltaY = 0; + } + + if (mScrollDeltaX!=0 || mScrollDeltaY!=0) { + if (isDragging) { + mScrollTimer->singleShot(100,this,&SynEdit::onDraggingScrollTimeout); + } else { + mScrollTimer->singleShot(100,this,&SynEdit::onScrollTimeout); + } + } } void SynEdit::doBlockIndent() @@ -2844,11 +2908,6 @@ void SynEdit::decPaintLock() } } -bool SynEdit::mouseCapture() -{ - return hasMouseTracking(); -} - int SynEdit::clientWidth() { return viewport()->size().width(); @@ -5988,7 +6047,7 @@ void SynEdit::mouseReleaseEvent(QMouseEvent *event) processGutterClick(event); } - mScrollTimer->stop(); + //mScrollTimer->stop(); // if ((button = ) and (Shift = [ssRight]) and Assigned(PopupMenu) then // exit; //setMouseTracking(false); @@ -6011,9 +6070,6 @@ void SynEdit::mouseMoveEvent(QMouseEvent *event) Qt::MouseButtons buttons = event->buttons(); int X=event->pos().x(); int Y=event->pos().y(); -// if (!hasMouseTracking()) -// return; - if ((mStateFlags.testFlag(SynStateFlag::sfWaitForDragging))) { if ( ( event->pos() - mMouseDownPos).manhattanLength()>=QApplication::startDragDistance()) { mStateFlags.setFlag(SynStateFlag::sfWaitForDragging,false); @@ -6027,18 +6083,17 @@ void SynEdit::mouseMoveEvent(QMouseEvent *event) //drag->setPixmap(iconPixmap); //BeginDrag(false); } -// } else if ((buttons == Qt::LeftButton) && (X > mGutterWidth)) { } else if ((buttons == Qt::LeftButton)) { - // should we begin scrolling? - computeScroll(X, Y); - DisplayCoord P = pixelsToNearestRowColumn(X, Y); - P.Row = minMax(P.Row, 1, displayLineCount()); - if (mScrollDeltaX != 0) - P.Column = displayX(); - if (mScrollDeltaY != 0) - P.Row = displayY(); - internalSetCaretXY(displayToBufferPos(P)); - setBlockEnd(caretXY()); + // should we begin scrolling? + computeScroll(X, Y,false); + DisplayCoord P = pixelsToNearestRowColumn(X, Y); + P.Row = minMax(P.Row, 1, displayLineCount()); + if (mScrollDeltaX != 0) + P.Column = displayX(); + if (mScrollDeltaY != 0) + P.Row = displayY(); + internalSetCaretXY(displayToBufferPos(P)); + setBlockEnd(caretXY()); } else if (buttons == Qt::NoButton) { updateMouseCursor(); } @@ -6132,7 +6187,6 @@ QVariant SynEdit::inputMethodQuery(Qt::InputMethodQuery property) const void SynEdit::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasFormat("text/plain")) { - mDragging = true; event->acceptProposedAction(); mDragCaretSave = caretXY(); mDragSelBeginSave = blockBegin(); @@ -6148,21 +6202,26 @@ void SynEdit::dragEnterEvent(QDragEnterEvent *event) void SynEdit::dropEvent(QDropEvent *event) { + //mScrollTimer->stop(); mUndoList->BeginBlock(); auto action = finally([this] { mUndoList->EndBlock(); }); + BufferCoord coord = displayToBufferPos(pixelsToNearestRowColumn(event->pos().x(), + event->pos().y())); + int topLine = mTopLine; + int leftChar = mLeftChar; if (event->proposedAction() == Qt::DropAction::MoveAction) { setBlockBegin(mDragSelBeginSave); setBlockEnd(mDragSelEndSave); setSelText(""); } - BufferCoord coord = displayToBufferPos(pixelsToNearestRowColumn(event->pos().x(), - event->pos().y())); + setTopLine(topLine); + setLeftChar(leftChar); setCaretXY(coord); setSelText(event->mimeData()->text()); event->acceptProposedAction(); - mDragging = false; + } void SynEdit::dragMoveEvent(QDragMoveEvent *event) @@ -6174,15 +6233,7 @@ void SynEdit::dragMoveEvent(QDragMoveEvent *event) } // should we begin scrolling? computeScroll(event->pos().x(), - event->pos().y()); -// DisplayCoord P = pixelsToNearestRowColumn(X, Y); -// P.Row = minMax(P.Row, 1, displayLineCount()); -// if (mScrollDeltaX != 0) -// P.Column = displayX(); -// if (mScrollDeltaY != 0) -// P.Row = displayY(); -// internalSetCaretXY(displayToBufferPos(P)); -// setBlockEnd(caretXY()); + event->pos().y(),true); BufferCoord coord = displayToBufferPos(pixelsToNearestRowColumn(event->pos().x(), event->pos().y())); @@ -6198,8 +6249,6 @@ void SynEdit::dragLeaveEvent(QDragLeaveEvent *) // setBlockBegin(mDragSelBeginSave); // setBlockEnd(mDragSelEndSave); // showCaret(); - mScrollTimer->stop(); - mDragging = false; } int SynEdit::maxScrollHeight() const @@ -6575,46 +6624,10 @@ void SynEdit::onGutterChanged() void SynEdit::onScrollTimeout() { - QPoint iMousePos; - DisplayCoord C; - int X, Y; - - iMousePos = QCursor::pos(); - iMousePos = mapFromGlobal(iMousePos); - C = pixelsToRowColumn(iMousePos.x(), iMousePos.y()); - C.Row = minMax(C.Row, 1, displayLineCount()); - if (mScrollDeltaX != 0) { - setLeftChar(leftChar() + mScrollDeltaX); - X = leftChar(); - if (mScrollDeltaX > 0) // scrolling right? - X+=charsInWindow(); - C.Column = X; - } - if (mScrollDeltaY != 0) { - if (QApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier)) - setTopLine(mTopLine + mScrollDeltaY * mLinesInWindow); - else - setTopLine(mTopLine + mScrollDeltaY); - Y = mTopLine; - if (mScrollDeltaY > 0) // scrolling down? - Y+=mLinesInWindow - 1; - C.Row = minMax(Y, 1, displayLineCount()); - } - BufferCoord vCaret = displayToBufferPos(C); - if ((caretX() != vCaret.Char) || (caretY() != vCaret.Line)) { - // changes to line / column in one go - incPaintLock(); - auto action = finally([this]{ - decPaintLock(); - }); - internalSetCaretXY(vCaret); - - // if MouseCapture is True we're changing selection. otherwise we're dragging - if (mDragging) { - setBlockBegin(mDragSelBeginSave); - setBlockEnd(mDragSelEndSave); - } else - setBlockEnd(caretXY()); - } - computeScroll(iMousePos.x(), iMousePos.y()); + doMouseScroll(false); +} + +void SynEdit::onDraggingScrollTimeout() +{ + doMouseScroll(true); } diff --git a/RedPandaIDE/qsynedit/SynEdit.h b/RedPandaIDE/qsynedit/SynEdit.h index d5fcc091..da0571d0 100644 --- a/RedPandaIDE/qsynedit/SynEdit.h +++ b/RedPandaIDE/qsynedit/SynEdit.h @@ -432,11 +432,10 @@ protected: private: void clearAreaList(SynEditingAreaList areaList); void computeCaret(int X, int Y); - void computeScroll(int X, int Y); + void computeScroll(int X, int Y, bool isDragging); void incPaintLock(); void decPaintLock(); - bool mouseCapture(); int clientWidth(); int clientHeight(); int clientTop(); @@ -562,6 +561,7 @@ private: void doComment(); void doUncomment(); void doToggleComment(); + void doMouseScroll(bool isDragging); private slots: @@ -575,6 +575,7 @@ private slots: void onLinesPutted(int index, int count); void onRedoAdded(); void onScrollTimeout(); + void onDraggingScrollTimeout(); void onUndoAdded(); void onSizeOrFontChanged(bool bFont); void onChanged(); From db61432d36c409072f6f23bbd446ad4ebc8c48d3 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Fri, 26 Nov 2021 19:54:05 +0800 Subject: [PATCH 30/32] - fix: dragging text from lines in the front to lines back will cause error - fix: dragging text onto itself should do nothing --- NEWS.md | 2 + RedPandaIDE/qsynedit/SynEdit.cpp | 63 +++++++++++++++++++++++++------- RedPandaIDE/qsynedit/Types.cpp | 29 +++++++++++++++ RedPandaIDE/qsynedit/Types.h | 5 +++ 4 files changed, 85 insertions(+), 14 deletions(-) diff --git a/NEWS.md b/NEWS.md index 0f3c1bbc..26e49e80 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,8 @@ Version 0.10.2 For Dev-C++ 7 Beta - fix: select by mouse can't correctly set mouse's column position - fix: dragging out of the editor and back will cause error + - fix: dragging text from lines in the front to lines back will cause error + - fix: dragging text onto itself should do nothing Version 0.10.1 For Dev-C++ 7 Beta - fix: can't correctly expand watch expression that has spaces in it diff --git a/RedPandaIDE/qsynedit/SynEdit.cpp b/RedPandaIDE/qsynedit/SynEdit.cpp index 201874c0..9c733be6 100644 --- a/RedPandaIDE/qsynedit/SynEdit.cpp +++ b/RedPandaIDE/qsynedit/SynEdit.cpp @@ -6203,23 +6203,58 @@ void SynEdit::dragEnterEvent(QDragEnterEvent *event) void SynEdit::dropEvent(QDropEvent *event) { //mScrollTimer->stop(); - mUndoList->BeginBlock(); - auto action = finally([this] { - mUndoList->EndBlock(); - }); + BufferCoord coord = displayToBufferPos(pixelsToNearestRowColumn(event->pos().x(), event->pos().y())); - int topLine = mTopLine; - int leftChar = mLeftChar; - if (event->proposedAction() == Qt::DropAction::MoveAction) { - setBlockBegin(mDragSelBeginSave); - setBlockEnd(mDragSelEndSave); - setSelText(""); - } - setTopLine(topLine); - setLeftChar(leftChar); setCaretXY(coord); - setSelText(event->mimeData()->text()); + if (coord>=mDragSelBeginSave && coord<=mDragSelEndSave) { + //do nothing if drag onto itself + } else if (event->proposedAction() == Qt::DropAction::CopyAction) { + //just copy it + setSelText(event->mimeData()->text()); + } else if (event->proposedAction() == Qt::DropAction::MoveAction) { + int topLine = mTopLine; + int leftChar = mLeftChar; + mUndoList->BeginBlock(); + if (coord < mDragSelBeginSave ) { + //delete old + setBlockBegin(mDragSelBeginSave); + setBlockEnd(mDragSelEndSave); + setSelText(""); + //paste to new position + setTopLine(topLine); + setLeftChar(leftChar); + setCaretXY(coord); + setSelText(event->mimeData()->text()); + } else { + //paste to new position + setTopLine(topLine); + setLeftChar(leftChar); + setCaretXY(coord); + setSelText(event->mimeData()->text()); + //delete old + setBlockBegin(mDragSelBeginSave); + setBlockEnd(mDragSelEndSave); + setSelText(""); + //set caret to right pos + if (mDragSelBeginSave.Line == mDragSelEndSave.Line) { + if (coord.Line == mDragSelEndSave.Line) { + coord.Char -= mDragSelEndSave.Char-mDragSelBeginSave.Char; + } + } else { + if (coord.Line == mDragSelEndSave.Line) { + coord.Char -= mDragSelEndSave.Char-1; + } else { + coord.Line -= mDragSelEndSave.Line-mDragSelBeginSave.Line; + topLine -= mDragSelEndSave.Line-mDragSelBeginSave.Line; + } + } + setTopLine(topLine); + setLeftChar(leftChar); + setCaretXY(coord); + } + mUndoList->EndBlock(); + } event->acceptProposedAction(); } diff --git a/RedPandaIDE/qsynedit/Types.cpp b/RedPandaIDE/qsynedit/Types.cpp index e4e985eb..0de4c4bf 100644 --- a/RedPandaIDE/qsynedit/Types.cpp +++ b/RedPandaIDE/qsynedit/Types.cpp @@ -239,3 +239,32 @@ bool BufferCoord::operator==(const BufferCoord &coord) { return coord.Char == Char && coord.Line == Line; } + +bool BufferCoord::operator>=(const BufferCoord &coord) +{ + return (Line > coord.Line) + || (Line == coord.Line && Char >= coord.Char); +} + +bool BufferCoord::operator>(const BufferCoord &coord) +{ + return (Line > coord.Line) + || (Line == coord.Line && Char > coord.Char); +} + +bool BufferCoord::operator<(const BufferCoord &coord) +{ + return (Line < coord.Line) + || (Line == coord.Line && Char < coord.Char); +} + +bool BufferCoord::operator<=(const BufferCoord &coord) +{ + return (Line < coord.Line) + || (Line == coord.Line && Char <= coord.Char); +} + +bool BufferCoord::operator!=(const BufferCoord &coord) +{ + return coord.Char != Char || coord.Line != Line; +} diff --git a/RedPandaIDE/qsynedit/Types.h b/RedPandaIDE/qsynedit/Types.h index ce7fe313..5df31c40 100644 --- a/RedPandaIDE/qsynedit/Types.h +++ b/RedPandaIDE/qsynedit/Types.h @@ -11,6 +11,11 @@ struct BufferCoord { int Char; int Line; bool operator==(const BufferCoord& coord); + bool operator>=(const BufferCoord& coord); + bool operator>(const BufferCoord& coord); + bool operator<(const BufferCoord& coord); + bool operator<=(const BufferCoord& coord); + bool operator!=(const BufferCoord& coord); }; class SynEdit; From 564bf02e59c03e36ce0957fca10fb9d88c2dd651 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Fri, 26 Nov 2021 20:44:27 +0800 Subject: [PATCH 31/32] =?UTF-8?q?-=20fix=EF=BC=9Alicense=20info=20in=20the?= =?UTF-8?q?=20about=20dialog=20should=20be=20readonly?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NEWS.md | 1 + RedPandaIDE/version.h | 2 +- RedPandaIDE/widgets/aboutdialog.ui | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 26e49e80..8af7b668 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,6 +3,7 @@ Version 0.10.2 For Dev-C++ 7 Beta - fix: dragging out of the editor and back will cause error - fix: dragging text from lines in the front to lines back will cause error - fix: dragging text onto itself should do nothing + - fix:license info in the about dialog should be readonly Version 0.10.1 For Dev-C++ 7 Beta - fix: can't correctly expand watch expression that has spaces in it diff --git a/RedPandaIDE/version.h b/RedPandaIDE/version.h index 5285c2e7..ee6dee7a 100644 --- a/RedPandaIDE/version.h +++ b/RedPandaIDE/version.h @@ -2,6 +2,6 @@ #define VERSION_H #include -#define DEVCPP_VERSION "beta.0.10.1" +#define DEVCPP_VERSION "beta.0.10.2" #endif // VERSION_H diff --git a/RedPandaIDE/widgets/aboutdialog.ui b/RedPandaIDE/widgets/aboutdialog.ui index 8722dbbb..ed260e9a 100644 --- a/RedPandaIDE/widgets/aboutdialog.ui +++ b/RedPandaIDE/widgets/aboutdialog.ui @@ -54,6 +54,9 @@ + + true + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by From dfce6e714663030f1093c0a78e1b92abe6a43d45 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Sat, 27 Nov 2021 09:36:49 +0800 Subject: [PATCH 32/32] - enhancement: change project name in the project view --- NEWS.md | 1 + RedPandaIDE/project.cpp | 12 +++++++++--- RedPandaIDE/project.h | 2 -- .../environmentfileassociationwidget.cpp | 1 - RedPandaIDE/utils.cpp | 1 - 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/NEWS.md b/NEWS.md index 8af7b668..66d50f5e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,7 @@ Version 0.10.2 For Dev-C++ 7 Beta - fix: dragging text from lines in the front to lines back will cause error - fix: dragging text onto itself should do nothing - fix:license info in the about dialog should be readonly + - enhancement: change project name in the project view Version 0.10.1 For Dev-C++ 7 Beta - fix: can't correctly expand watch expression that has spaces in it diff --git a/RedPandaIDE/project.cpp b/RedPandaIDE/project.cpp index 3257e6c9..c548b9d0 100644 --- a/RedPandaIDE/project.cpp +++ b/RedPandaIDE/project.cpp @@ -1597,6 +1597,7 @@ void Project::setName(const QString &newName) if (newName != mName) { mName = newName; mNode->text = newName; + setModified(true); } } @@ -1883,7 +1884,7 @@ Qt::ItemFlags ProjectModel::flags(const QModelIndex &index) const if (!p) return Qt::NoItemFlags; if (p==mProject->node().get()) - return Qt::ItemIsEnabled | Qt::ItemIsDropEnabled; + return Qt::ItemIsEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable; Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled; if (p->unitIndex<0) { flags.setFlag(Qt::ItemIsDropEnabled); @@ -1901,8 +1902,13 @@ bool ProjectModel::setData(const QModelIndex &index, const QVariant &value, int if (!node) return false; if (role == Qt::EditRole) { - if (node == mProject->node()) - return false; + if (node == mProject->node()) { + QString newName = value.toString().trimmed(); + if (newName.isEmpty()) + return false; + mProject->setName(newName); + return true; + } int idx = node->unitIndex; if (idx >= 0) { //change unit name diff --git a/RedPandaIDE/project.h b/RedPandaIDE/project.h index e5f6f392..bcd04b6e 100644 --- a/RedPandaIDE/project.h +++ b/RedPandaIDE/project.h @@ -2,8 +2,6 @@ #define PROJECT_H #include -#include -#include #include #include "projectoptions.h" #include "utils.h" diff --git a/RedPandaIDE/settingsdialog/environmentfileassociationwidget.cpp b/RedPandaIDE/settingsdialog/environmentfileassociationwidget.cpp index 89c70630..39e007ab 100644 --- a/RedPandaIDE/settingsdialog/environmentfileassociationwidget.cpp +++ b/RedPandaIDE/settingsdialog/environmentfileassociationwidget.cpp @@ -4,7 +4,6 @@ #include "../settings.h" #include -#include #include EnvironmentFileAssociationWidget::EnvironmentFileAssociationWidget(const QString& name, const QString& group, QWidget *parent) : diff --git a/RedPandaIDE/utils.cpp b/RedPandaIDE/utils.cpp index 1a7551a5..3dab6c78 100644 --- a/RedPandaIDE/utils.cpp +++ b/RedPandaIDE/utils.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include