From d3f7c872dd235db5c051857e2fcc39ea3a1e7e39 Mon Sep 17 00:00:00 2001 From: royqh1979 Date: Sun, 29 Aug 2021 22:08:43 +0800 Subject: [PATCH] - feature done: editor info tooltips --- RedPandaIDE/debugger.cpp | 16 +++++- RedPandaIDE/debugger.h | 5 ++ RedPandaIDE/editor.cpp | 76 +++++++++++++++++++++++------ RedPandaIDE/editor.h | 9 ++-- RedPandaIDE/mainwindow.cpp | 9 ++++ RedPandaIDE/mainwindow.h | 1 + RedPandaIDE/parser/cppparser.cpp | 24 +++++++-- RedPandaIDE/parser/cppparser.h | 1 + RedPandaIDE/qsynedit/KeyStrokes.cpp | 2 +- 9 files changed, 116 insertions(+), 27 deletions(-) diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index e04f6805..84dab777 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -132,6 +132,14 @@ void Debugger::sendCommand(const QString &command, const QString ¶ms, bool u } } +bool Debugger::commandRunning() +{ + if (mExecuting && mReader) { + return mReader->commandRunning(); + } + return false; +} + void Debugger::addBreakpoint(int line, const Editor* editor) { addBreakpoint(line,editor->filename()); @@ -402,7 +410,8 @@ void Debugger::syncFinishedParsing() // An evaluation variable has been processed. Forward the results if (mReader->doevalready) { - pMainWindow->updateDebugEval(mReader->mEvalValue); + //pMainWindow->updateDebugEval(mReader->mEvalValue); + emit evalValueReady(mReader->mEvalValue); mReader->mEvalValue=""; mReader->doevalready = false; } @@ -1328,6 +1337,11 @@ void DebugReader::stopDebug() mStop = true; } +bool DebugReader::commandRunning() +{ + return !mCmdQueue.isEmpty(); +} + void DebugReader::run() { diff --git a/RedPandaIDE/debugger.h b/RedPandaIDE/debugger.h index c3ad0b2c..aa28d296 100644 --- a/RedPandaIDE/debugger.h +++ b/RedPandaIDE/debugger.h @@ -172,6 +172,7 @@ public: bool updateWatch = true, bool showInConsole = false, DebugCommandSource source = DebugCommandSource::Other); + bool commandRunning(); //breakpoints void addBreakpoint(int line, const Editor* editor); @@ -215,6 +216,8 @@ public: RegisterModel *registerModel() const; +signals: + void evalValueReady(const QString& s); public slots: void stop(); @@ -255,6 +258,8 @@ public: void setDebuggerPath(const QString &debuggerPath); void stopDebug(); + bool commandRunning(); + bool invalidateAllVars() const; void setInvalidateAllVars(bool invalidateAllVars); diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index f3569335..8257641d 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include "iconsmanager.h" #include "debugger.h" #include "editorlist.h" @@ -585,12 +586,11 @@ bool Editor::event(QEvent *event) QHelpEvent *helpEvent = static_cast(event); BufferCoord p; TipType reason = getTipType(helpEvent->pos(),p); - qDebug()<<(int)reason; PSyntaxIssue pError; int line ; if (reason == TipType::Error) { pError = getSyntaxIssueAtPosition(p); - } else if ((reason == TipType::None) && GetLineOfMouse(line)) { + } else if ((reason == TipType::None) && PointToLine(helpEvent->pos(),line)) { //it's on gutter //see if its error; PSyntaxIssueList issues = getSyntaxIssuesAtLine(line); @@ -627,7 +627,6 @@ bool Editor::event(QEvent *event) s = pError->token; break; case TipType::None: - //fText.Cursor := crIBeam; // nope cancelHint(); event->ignore(); return true; @@ -639,6 +638,12 @@ bool Editor::event(QEvent *event) // if (s = fCurrentWord) and (fText.Hint<>'') then s = s.trimmed(); if ((s == mCurrentWord) && (mCurrentTipType == reason)) { + QApplication* app = dynamic_cast(QApplication::instance()); + if (app->keyboardModifiers().testFlag(Qt::ControlModifier)) { + setCursor(Qt::PointingHandCursor); + } else { + setCursor(Qt::ArrowCursor); + } event->ignore(); return true; // do NOT remove hint when subject stays the same } @@ -648,11 +653,6 @@ bool Editor::event(QEvent *event) mCurrentWord = s; mCurrentTipType = reason; - // We are allowed to change the cursor -// if (ssCtrl in Shift) then -// fText.Cursor := crHandPoint -// else -// fText.Cursor := crIBeam; // Determine what to do with subject QString hint = ""; @@ -671,19 +671,27 @@ bool Editor::event(QEvent *event) if (!mCompletionPopup->isVisible() && !mHeaderCompletionPopup->isVisible()) { if (pMainWindow->debugger()->executing()) { - hint = getDebugHint(s); + showDebugHint(s,line); } else { //if devEditor.ParserHints { hint = getParserHint(s, p.Line); } } break; case TipType::Error: - hint = getErrorHint(s); + hint = getErrorHint(pError); } if (!hint.isEmpty()) { + QApplication* app = dynamic_cast(QApplication::instance()); + if (app->keyboardModifiers().testFlag(Qt::ControlModifier)) { + setCursor(Qt::PointingHandCursor); + } else { + setCursor(Qt::ArrowCursor); + } QToolTip::showText(helpEvent->globalPos(),hint); - } else event->ignore(); + } else { + event->ignore(); + } } return SynEdit::event(event); } @@ -994,6 +1002,15 @@ void Editor::onGutterClicked(Qt::MouseButton button, int , int , int line) mGutterClickedLine = line; } +void Editor::onTipEvalValueReady(const QString &value) +{ + if (mCurrentWord == mCurrentDebugTipWord) { + QToolTip::showText(QCursor::pos(), mCurrentDebugTipWord + " = " + value ); + } + disconnect(pMainWindow->debugger(), &Debugger::evalValueReady, + this, &Editor::onTipEvalValueReady); +} + QChar Editor::getCurrentChar() { if (lineText().length()name() == SYNS_AttrAreaAIdentifier) + } else if (attr->name() == SYNS_AttrIdentifier) return TipType::Identifier; else if (attr->name() == SYNS_AttrPreprocessor) return TipType::Preprocessor; @@ -1888,6 +1905,7 @@ void Editor::cancelHint() QToolTip::hideText(); mCurrentWord = ""; mCurrentTipType = TipType::None; + setCursor(Qt::IBeamCursor); } QString Editor::getFileHint(const QString &s) @@ -1929,18 +1947,46 @@ QString Editor::getParserHint(const QString &s, int line) mFilename,line); } else if (statement->line>0) { QFileInfo fileInfo(statement->fileName); - result = mParser->prettyPrintStatement(statement) + " - " + + result = mParser->prettyPrintStatement(statement,mFilename, line) + " - " + QString(" %1 (%2) ") .arg(fileInfo.fileName()) .arg(statement->line) + tr("Ctrl+click for more info"); } else { // hard defines - result = mParser->prettyPrintStatement(statement); + result = mParser->prettyPrintStatement(statement, mFilename); } // Result := StringReplace(Result, '|', #5, [rfReplaceAll]); return result; } +void Editor::showDebugHint(const QString &s, int line) +{ + PStatement statement = mParser->findStatementOf(s,mFilename,line); + if (statement) { + if (statement->kind != StatementKind::skVariable + || statement->kind != StatementKind::skGlobalVariable + || statement->kind != StatementKind::skLocalVariable + || statement->kind != StatementKind::skParameter) { + return; + } + } + if (pMainWindow->debugger()->commandRunning()) + return; + connect(pMainWindow->debugger(), &Debugger::evalValueReady, + this, &Editor::onTipEvalValueReady); + mCurrentDebugTipWord = s; + pMainWindow->debugger()->sendCommand("print",s,false); +} + +QString Editor::getErrorHint(const PSyntaxIssue& issue) +{ + if (issue) { + return issue->hint; + } else { + return ""; + } +} + QString Editor::getHintForFunction(const PStatement &statement, const PStatement &scopeStatement, const QString& filename, int line) { QString result; @@ -1953,7 +1999,7 @@ QString Editor::getHintForFunction(const PStatement &statement, const PStatement continue; if (!result.isEmpty()) result += "
"; - result = mParser->prettyPrintStatement(childStatement) + " - " + + result = mParser->prettyPrintStatement(childStatement,filename,line) + " - " + QString(" %1 (%2) ") .arg(filename) .arg(childStatement->line) diff --git a/RedPandaIDE/editor.h b/RedPandaIDE/editor.h index 849f708f..74c3a1d5 100644 --- a/RedPandaIDE/editor.h +++ b/RedPandaIDE/editor.h @@ -143,13 +143,11 @@ public: const PCppParser &parser() const; -signals: - - protected slots: void onModificationChanged(bool status) ; void onStatusChanged(SynStatusChanges changes); void onGutterClicked(Qt::MouseButton button, int x, int y, int line); + void onTipEvalValueReady(const QString& value); private: QChar getCurrentChar(); @@ -188,8 +186,8 @@ private: void cancelHint(); QString getFileHint(const QString& s); QString getParserHint(const QString& s, int line); - QString getDebugHint(const QString& s); - QString getErrorHint(const QString& s); + void showDebugHint(const QString& s,int line); + QString getErrorHint(const PSyntaxIssue& issue); QString getHintForFunction(const PStatement& statement, const PStatement& scope, const QString& filename, int line); @@ -219,6 +217,7 @@ private: int mLastIdCharPressed; bool mUseCppSyntax; QString mCurrentWord; + QString mCurrentDebugTipWord; TipType mCurrentTipType; // QWidget interface diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index da840358..1ed591f0 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -1588,6 +1588,8 @@ void MainWindow::onDebugEvaluateInput() { QString s=ui->cbEvaluate->currentText().trimmed(); if (!s.isEmpty()) { + connect(mDebugger, &Debugger::evalValueReady, + this, &MainWindow::onEvalValueReady); mDebugger->sendCommand("print",s,false); } } @@ -1636,6 +1638,13 @@ void MainWindow::onEndParsing(int total, int) } } +void MainWindow::onEvalValueReady(const QString &value) +{ + updateDebugEval(value); + disconnect(mDebugger, &Debugger::evalValueReady, + this, &MainWindow::onEvalValueReady); +} + void MainWindow::on_actionFind_triggered() { Editor *e = mEditorList->getEditor(); diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index f5763565..71c91f26 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -214,6 +214,7 @@ public slots: void onParserProgress(const QString& fileName, int total, int current); void onStartParsing(); void onEndParsing(int total, int updateView); + void onEvalValueReady(const QString& value); private: void setupActions(); diff --git a/RedPandaIDE/parser/cppparser.cpp b/RedPandaIDE/parser/cppparser.cpp index 1f2e080e..601c17f4 100644 --- a/RedPandaIDE/parser/cppparser.cpp +++ b/RedPandaIDE/parser/cppparser.cpp @@ -813,6 +813,19 @@ void CppParser::unFreeze() mLockCount--; } +QString CppParser::getScopePrefix(const PStatement& statement){ + switch (statement->classScope) { + case StatementClassScope::scsPublic: + return "public"; + case StatementClassScope::scsPrivate: + return "private"; + case StatementClassScope::scsProtected: + return "protected"; + default: + return ""; + } +} + QString CppParser::prettyPrintStatement(const PStatement& statement, const QString& filename, int line) { QString result; @@ -836,10 +849,10 @@ QString CppParser::prettyPrintStatement(const PStatement& statement, const QStri case StatementKind::skParameter: case StatementKind::skClass: if (statement->scope!= StatementScope::ssLocal) - result = getScopePrefix(statement); // public + result = getScopePrefix(statement)+ ' '; // public result += statement->type + ' '; // void result += statement->fullName; // A::B::C::Bar - result += getArgsSuffix(statement); // (int a) + result += statement->args; // (int a) break; case StatementKind::skNamespace: result = statement->fullName; // Bar @@ -849,17 +862,18 @@ QString CppParser::prettyPrintStatement(const PStatement& statement, const QStri result += QObject::tr("constructor") + ' '; // constructor result += statement->type + ' '; // void result += statement->fullName; // A::B::C::Bar - result += getArgsSuffix(statement); // (int a) + result += statement->args; // (int a) break; case StatementKind::skDestructor: result = getScopePrefix(statement); // public result += QObject::tr("destructor") + ' '; // constructor result += statement->type + ' '; // void result += statement->fullName; // A::B::C::Bar - result += getArgsSuffix(statement); // (int a) + result += statement->args; // (int a) break; } } + return result; } QString CppParser::getFirstTemplateParam(const PStatement& statement, @@ -3097,7 +3111,7 @@ void CppParser::fillListOfFunctions(const QString& fileName, int line, ) { if (line < child->line && (child->fileName == fileName)) continue; - list.append(prettyPrintStatement(child)); + list.append(prettyPrintStatement(child,child->fileName,child->line)); } } } diff --git a/RedPandaIDE/parser/cppparser.h b/RedPandaIDE/parser/cppparser.h index eae6ba34..64211271 100644 --- a/RedPandaIDE/parser/cppparser.h +++ b/RedPandaIDE/parser/cppparser.h @@ -227,6 +227,7 @@ private: PStatement getIncompleteClass( const QString& command, const PStatement& parentScope); + QString getScopePrefix(const PStatement& statement); StatementScope getScope(); QString getStatementKey(const QString& sName, const QString& sType, diff --git a/RedPandaIDE/qsynedit/KeyStrokes.cpp b/RedPandaIDE/qsynedit/KeyStrokes.cpp index e83595a5..43d41926 100644 --- a/RedPandaIDE/qsynedit/KeyStrokes.cpp +++ b/RedPandaIDE/qsynedit/KeyStrokes.cpp @@ -21,7 +21,7 @@ QKeySequence SynEditKeyStroke::keySequence() const void SynEditKeyStroke::setKeySequence(QKeySequence &keySequence) { - if (keySequence.isEmpty()<=0) + if (keySequence.isEmpty()) return; decodeKey(keySequence[0],mKey,mKeyModifiers); if (keySequence.count()>1) {