work save

This commit is contained in:
royqh1979@gmail.com 2021-08-01 01:06:43 +08:00
parent 08bb97ace1
commit d89866803c
10 changed files with 294 additions and 105 deletions

View File

@ -9,11 +9,13 @@
#include <QFileInfo>
#include <QMessageBox>
#include <QMessageBox>
#include <QDebug>
Debugger::Debugger(QObject *parent) : QObject(parent)
{
mBreakpointModel=new BreakpointModel(this);
mBacktraceModel=new BacktraceModel(this);
mWatchModel = new WatchModel(this);
mExecuting = false;
mUseUTF8 = false;
mReader = nullptr;
@ -93,24 +95,17 @@ void Debugger::clearUpReader()
mBacktraceModel->clear();
// Application.HintHidePause := 2500;
// WatchView.Items.BeginUpdate;
// try
// //Clear all watch values
// for I := 0 to WatchVarList.Count - 1 do begin
// WatchVar := PWatchVar(WatchVarList.Items[I]);
// WatchVar^.Node.Text := WatchVar^.Name + ' = '+Lang[ID_MSG_EXECUTE_TO_EVALUATE];
// // Delete now invalid children
// WatchVar^.Node.DeleteChildren;
// end;
// finally
// WatchView.Items.EndUpdate;
// end;
for(PWatchVar var:mWatchModel->watchVars()) {
invalidateWatchVar(var);
}
}
}
WatchModel *Debugger::watchModel() const
{
return mWatchModel;
}
void Debugger::sendCommand(const QString &command, const QString &params, bool updateWatch, bool showInConsole, DebugCommandSource source)
{
if (mExecuting && mReader) {
@ -200,8 +195,7 @@ void Debugger::addWatchVar(const QString &namein)
PWatchVar var = std::make_shared<WatchVar>();
var->parent= nullptr;
var->name = namein;
var->value = tr("Execute to evaluate");
var->text = QString("%1 = %2").arg(var->name).arg(var->value);
var->text = QString("%1 = %2").arg(var->name).arg(tr("Execute to evaluate"));
var->gdbIndex = -1;
mWatchModel->addWatchVar(var);
@ -218,15 +212,13 @@ void Debugger::renameWatchVar(const QString &oldname, const QString &newname)
var = mWatchModel->findWatchVar(oldname);
if (var) {
var->name = newname;
var->value = tr("Execute to evaluate");
var->text = QString("%1 = %1").arg(var->name).arg(var->value);
if (mExecuting && var->gdbIndex!=-1)
sendRemoveWatchCommand(var);
invalidateWatchVar(var);
if (mExecuting) {
if (var->gdbIndex!=-1)
sendRemoveWatchCommand(var);
sendWatchCommand(var);
}
mWatchModel->notifyUpdated(var);
}
}
@ -245,9 +237,7 @@ void Debugger::deleteWatchVars(bool deleteparent)
} else {
for(PWatchVar var:mWatchModel->watchVars()) {
sendRemoveWatchCommand(var);
var->gdbIndex = -1;
var->value = tr("Execute to evaluate");
var->text = QString("%1 = %1").arg(var->name).arg(var->value);
invalidateWatchVar(var);
}
}
}
@ -264,9 +254,36 @@ void Debugger::sendAllWatchvarsToDebugger()
}
}
void Debugger::invalidateWatchVar(const QString &name)
{
PWatchVar var = mWatchModel->findWatchVar(name);
if (var) {
invalidateWatchVar(var);
}
}
void Debugger::invalidateWatchVar(PWatchVar var)
{
//toto
var->gdbIndex = -1;
QString value;
if (mExecuting) {
value = tr("Not found in current context");
} else {
value = tr("Execute to evaluate");
}
var->text = QString("%1 = %2").arg(var->name).arg(value);
var->children.clear();
mWatchModel->notifyUpdated(var);
}
PWatchVar Debugger::findWatchVar(const QString &name)
{
return mWatchModel->findWatchVar(name);
}
void Debugger::notifyWatchVarUpdated(PWatchVar var)
{
mWatchModel->notifyUpdated(var);
}
void Debugger::updateDebugInfo()
@ -410,10 +427,6 @@ void Debugger::syncFinishedParsing()
// CPUForm.OnAssemblerReady;
}
//if dobacktraceready then
// MainForm.OnBacktraceReady;
if (mReader->doupdateexecution) {
if (mReader->mCurrentCmd && mReader->mCurrentCmd->source == DebugCommandSource::Console) {
pMainWindow->setActiveBreakpoint(mReader->mBreakPointFile, mReader->mBreakPointLine,false);
@ -756,17 +769,16 @@ void DebugReader::handleDisplay()
if (!findAnnotation(AnnotationType::TDisplayExpression))
return;
QString watchName = getNextLine(); // watch name
// Find parent we're talking about
auto result = mWatchVarList.find(watchName);
if (result != mWatchVarList.end()) {
PWatchVar watchVar = result.value();
// Find watchVar we're talking about
PWatchVar watchVar = mDebugger->findWatchVar(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();
processWatchOutput(watchVar);
mDebugger->notifyWatchVarUpdated(watchVar);
}
}
@ -781,15 +793,8 @@ void DebugReader::handleError()
int tail = s.lastIndexOf('\"');
QString watchName = s.mid(head+1, tail-head-1);
// Update current...
auto result = mWatchVarList.find(watchName);
if (result != mWatchVarList.end()) {
PWatchVar watchVar = result.value();
//todo: update watch value to invalid
mDebugger->invalidateWatchVar(watchVar);
watchVar->gdbIndex = -1;
dorescanwatches = true;
}
// Update current..
mDebugger->invalidateWatchVar(watchName);
}
}
@ -804,6 +809,9 @@ void DebugReader::handleFrames()
// Is this a backtrace dump?
if (s.startsWith("#")) {
if (s.startsWith("#0")) {
mDebugger->backtraceModel()->clear();
}
// Find function name
if (!findAnnotation(AnnotationType::TFrameFunctionName))
return;
@ -1037,7 +1045,6 @@ void DebugReader::processDebugOutput()
dobacktraceready = false;
dodisassemblerready = false;
doregistersready = false;
dorescanwatches = false;
doevalready = false;
doprocessexited = false;
doupdateexecution = false;
@ -1137,11 +1144,63 @@ QString DebugReader::processEvalOutput()
}
result += nextLine;
} while (!shouldExit);
return result;
}
void DebugReader::processWatchOutput(PWatchVar WatchVar)
void DebugReader::processWatchOutput(PWatchVar watchVar)
{
//todo
// // 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->text = "";
// Process output parsed by ProcessEvalStruct
QString s = watchVar->name + " = " + processEvalOutput();
// add placeholder name for variable name so we can format structs using one rule
// Add children based on indent
QStringList lines = TextToLines(s);
PWatchVar parentVar=watchVar;
for (const QString& line:lines) {
// Format node text. Remove trailing comma
QString nodeText = line.trimmed();
if (nodeText.endsWith(',')) {
nodeText.remove(nodeText.length()-1);
}
if (nodeText.endsWith('{')) { // new member struct
if (parentVar->text.isEmpty()) { // root node, replace text only
parentVar->text = nodeText;
} else {
PWatchVar newVar = std::shared_ptr<WatchVar>();
newVar->parent = parentVar.get();
newVar->name = "";
newVar->text = nodeText;
newVar->gdbIndex = -1;
parentVar->children.append(newVar);
parentVar = newVar;
}
} else if (nodeText.startsWith('}')) { // end of struct, change parent
if (parentVar->parent!=nullptr) {
parentVar = std::shared_ptr<WatchVar>(parentVar->parent);
}
} else { // next parent member/child
if (parentVar->text.isEmpty()) { // root node, replace text only
parentVar->text = nodeText;
} else {
PWatchVar newVar = std::shared_ptr<WatchVar>();
newVar->parent = parentVar.get();
newVar->name = "";
newVar->text = nodeText;
newVar->gdbIndex = -1;
parentVar->children.append(newVar);
}
}
}
// TODO: remember expansion state
}
void DebugReader::runNextCmd()
@ -1278,7 +1337,7 @@ void DebugReader::run()
QByteArray buffer;
QByteArray readed;
while (true) {
mProcess->waitForFinished(100);
mProcess->waitForFinished(1);
if (mProcess->state()!=QProcess::Running) {
break;
}
@ -1298,6 +1357,8 @@ void DebugReader::run()
runNextCmd();
} else if (!mCmdRunning && readed.isEmpty()){
runNextCmd();
} else if (readed.isEmpty()){
msleep(100);
}
}
if (errorOccurred) {
@ -1499,6 +1560,7 @@ QVariant WatchModel::data(const QModelIndex &index, int role) const
WatchVar* item = static_cast<WatchVar*>(index.internalPointer());
switch (role) {
case Qt::DisplayRole:
qDebug()<<"item->text:"<<item->text;
return item->text;
}
return QVariant();
@ -1538,7 +1600,7 @@ QModelIndex WatchModel::parent(const QModelIndex &index) const
return QModelIndex();
}
WatchVar* childItem = static_cast<WatchVar*>(index.internalPointer());
WatchVar* parentItem =childItem->parent;
WatchVar* parentItem = childItem->parent;
//parent is root
if (parentItem == nullptr) {
@ -1649,5 +1711,6 @@ void WatchModel::notifyUpdated(PWatchVar var)
}
if (row<0)
return;
qDebug()<<"dataChanged"<<row<<":"<<var->text;
emit dataChanged(createIndex(row,0,var.get()),createIndex(row,0,var.get()));
}

View File

@ -53,13 +53,11 @@ using PWatchVar = std::shared_ptr<WatchVar>;
struct WatchVar {
QString name;
QString text;
QString value;
int gdbIndex;
QList<PWatchVar> children;
WatchVar * parent; //use raw point to prevent circular-reference
};
struct Breakpoint {
int line;
QString filename;
@ -124,9 +122,6 @@ class WatchModel: public QAbstractItemModel {
public:
explicit WatchModel(QObject *parent = nullptr);
QVariant data(const QModelIndex &index, int role) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const override;
QModelIndex index(int row, int column,
const QModelIndex &parent = QModelIndex()) const override;
@ -184,7 +179,10 @@ public:
void deleteWatchVars(bool deleteparent);
void invalidateAllVars();
void sendAllWatchvarsToDebugger();
void invalidateWatchVar(const QString& name);
void invalidateWatchVar(PWatchVar var);
PWatchVar findWatchVar(const QString& name);
void notifyWatchVarUpdated(PWatchVar var);
void updateDebugInfo();
@ -199,6 +197,8 @@ public:
int leftPageIndexBackup() const;
void setLeftPageIndexBackup(int leftPageIndexBackup);
WatchModel *watchModel() const;
public slots:
void stop();
signals:
@ -210,6 +210,7 @@ private:
void sendBreakpointCommand(PBreakpoint breakpoint);
void sendClearBreakpointCommand(int index);
void sendClearBreakpointCommand(PBreakpoint breakpoint);
private slots:
void syncFinishedParsing();
void onChangeDebugConsoleLastline(const QString& text);
@ -236,6 +237,9 @@ public:
void setDebuggerPath(const QString &debuggerPath);
void stopDebug();
bool invalidateAllVars() const;
void setInvalidateAllVars(bool invalidateAllVars);
signals:
void parseStarted();
void invalidateAllVars();
@ -291,7 +295,6 @@ private:
QProcess* mProcess;
QMap<QString,PWatchVar> mWatchVarList; // contains all parents
//fWatchView: TTreeView;
int mIndex;
int mBreakPointLine;
@ -305,7 +308,6 @@ private:
bool dobacktraceready;
bool dodisassemblerready;
bool doregistersready;
bool dorescanwatches;
bool doevalready;
bool doprocessexited;
bool doupdatecpuwindow;

View File

@ -357,57 +357,28 @@ void Editor::onGutterPaint(QPainter &painter, int aLine, int X, int Y)
X = 5;
Y += (this->textHeight() - 16) / 2;
PSyntaxIssueList lst = getSyntaxIssuesAtLine(aLine);
if (lst) {
bool hasError=false;
for (PSyntaxIssue issue : *lst) {
if (issue->issueType == CompileIssueType::Error) {
hasError = true;
break;;
}
}
if (hasError) {
painter.drawPixmap(X,Y,*(pIconsManager->syntaxError()));
} else {
painter.drawPixmap(X,Y,*(pIconsManager->syntaxWarning()));
}
return;
}
if (mActiveBreakpointLine == aLine) {
painter.drawPixmap(X,Y,*(pIconsManager->activeBreakpoint()));
} else if (hasBreakpoint(aLine)) {
painter.drawPixmap(X,Y,*(pIconsManager->breakpoint()));
} else {
PSyntaxIssueList lst = getSyntaxIssuesAtLine(aLine);
if (lst) {
bool hasError=false;
for (PSyntaxIssue issue : *lst) {
if (issue->issueType == CompileIssueType::Error) {
hasError = true;
break;;
}
}
if (hasError) {
painter.drawPixmap(X,Y,*(pIconsManager->syntaxError()));
} else {
painter.drawPixmap(X,Y,*(pIconsManager->syntaxWarning()));
}
return;
}
}
// if fActiveLine = Line then begin // prefer active line over breakpoints
// dmMain.GutterImages.Draw(ACanvas, X, Y, 1);
// drawn:=True;
// end else if HasBreakpoint(Line) <> -1 then begin
// dmMain.GutterImages.Draw(ACanvas, X, Y, 0);
// drawn:=True;
// end else if fErrorLine = Line then begin
// dmMain.GutterImages.Draw(ACanvas, X, Y, 2);
// drawn:=True;
// end;
// idx := CBUtils.FastIndexOf(fErrorList, Line);
// if idx>=0 then begin
// isError := False;
// lst:=TList(fErrorList.Objects[idx]);
// for j:=0 to lst.Count-1 do begin
// if PSyntaxError(lst[j])^.errorType = setError then begin
// isError := True;
// break;
// end;
// end;
// if isError then
// dmMain.GutterImages.Draw(ACanvas, X, Y, 2)
// else if not drawn then
// dmMain.GutterImages.Draw(ACanvas, X, Y, 3);
// end;
// Inc(Y, fText.LineHeight);
// end;
}
void Editor::onGetEditingAreas(int Line, SynEditingAreaList &areaList)
@ -1206,6 +1177,7 @@ void Editor::toggleBreakpoint(int line)
// MainForm.Debugger.RemoveBreakPoint(Line, self)
} else {
mBreakpointLines.insert(line);
//todo
// MainForm.Debugger.AddBreakPoint(Line, self);
}

View File

@ -52,6 +52,7 @@ int main(int argc, char *argv[])
qRegisterMetaType<PCompileIssue>("PCompileIssue");
qRegisterMetaType<PCompileIssue>("PCompileIssue&");
qRegisterMetaType<QVector<int>>("QVector<int>");
try {
@ -67,6 +68,8 @@ int main(int argc, char *argv[])
settings->environment().load();
settings->compilerSets().loadSets();
settings->editor().load();
settings->executor().load();
settings->debugger().load();
//Translation must be loaded after language setting is loaded
QTranslator trans;

View File

@ -12,6 +12,7 @@
#include <QCloseEvent>
#include <QComboBox>
#include <QFileDialog>
#include <QInputDialog>
#include <QLabel>
#include <QMessageBox>
#include <QTranslator>
@ -63,6 +64,7 @@ MainWindow::MainWindow(QWidget *parent)
ui->tblBreakpoints->setModel(mDebugger->breakpointModel());
ui->tblStackTrace->setModel(mDebugger->backtraceModel());
ui->watchView->setModel(mDebugger->watchModel());
ui->actionIndent->setShortcut(Qt::Key_Tab);
ui->actionUnIndent->setShortcut(Qt::Key_Tab | Qt::ShiftModifier);
@ -70,6 +72,7 @@ MainWindow::MainWindow(QWidget *parent)
ui->tableIssues->setErrorColor(QColor("Red"));
ui->tableIssues->setWarningColor(QColor("Orange"));
mMenuEncoding = new QMenu();
mMenuEncoding->setTitle(tr("File Encoding"));
mMenuEncoding->addAction(ui->actionAuto_Detect);
@ -296,7 +299,6 @@ void MainWindow::addDebugOutput(const QString &text)
ui->debugConsole->addLine("");
} else {
ui->debugConsole->addText(text);
qDebug()<<"add text"<<text;
}
}
@ -1371,3 +1373,28 @@ void MainWindow::on_actionContinue_triggered()
//fDebugger.RefreshWatchVars;
}
}
void MainWindow::on_actionAdd_Watch_triggered()
{
QString s = "";
Editor *e = mEditorList->getEditor();
if (e==nullptr)
return;
if (e->selAvail()) {
s = e->selText();
} else {
s = e->WordAtCursor();
}
bool isOk;
s=QInputDialog::getText(this,
tr("New Watch Expression"),
tr("Enter Watch Expression (it is recommended to use 'this->' for class members):"),
QLineEdit::Normal,
s,&isOk);
if (!isOk)
return;
s = s.trimmed();
if (!s.isEmpty()) {
mDebugger->addWatchVar(s);
}
}

View File

@ -151,6 +151,8 @@ private slots:
void on_actionContinue_triggered();
void on_actionAdd_Watch_triggered();
public slots:
void onCompileLog(const QString& msg);
void onCompileIssue(PCompileIssue issue);

View File

@ -85,7 +85,7 @@
<enum>QTabWidget::West</enum>
</property>
<property name="currentIndex">
<number>3</number>
<number>1</number>
</property>
<property name="usesScrollButtons">
<bool>true</bool>
@ -99,6 +99,33 @@
<attribute name="title">
<string>Watch</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<widget class="QTreeView" name="watchView">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabStructure">
<attribute name="title">
@ -557,6 +584,7 @@
<addaction name="actionRun_To_Cursor"/>
<addaction name="actionContinue"/>
<addaction name="actionStop_Execution"/>
<addaction name="actionAdd_Watch"/>
</widget>
<widget class="QMenu" name="menuEdit">
<property name="title">
@ -588,6 +616,12 @@
<property name="windowTitle">
<string>toolBar</string>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
@ -603,6 +637,12 @@
<property name="windowTitle">
<string>toolBar_2</string>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
@ -614,6 +654,12 @@
<property name="windowTitle">
<string>toolBar</string>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
@ -629,6 +675,12 @@
<property name="windowTitle">
<string>toolBar</string>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
@ -641,6 +693,8 @@
<addaction name="actionStep_Out"/>
<addaction name="actionContinue"/>
<addaction name="actionStop_Execution"/>
<addaction name="separator"/>
<addaction name="actionAdd_Watch"/>
</widget>
<action name="actionNew">
<property name="icon">
@ -1003,6 +1057,16 @@
<string>F4</string>
</property>
</action>
<action name="actionAdd_Watch">
<property name="icon">
<iconset>
<normalon>:/icons/images/newlook24/088-watch.png</normalon>
</iconset>
</property>
<property name="text">
<string>Add Watch...</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

View File

@ -926,6 +926,38 @@ bool SynEdit::selAvail() const
((mBlockBegin.Line != mBlockEnd.Line) && (mActiveSelectionMode != SynSelectionMode::smColumn));
}
QString SynEdit::WordAtCursor()
{
return WordAtRowCol(caretXY());
}
QString SynEdit::WordAtRowCol(const BufferCoord &XY)
{
if ((XY.Line >= 1) && (XY.Line <= mLines->count())) {
QString line = mLines->getString(XY.Line - 1);
int Len = line.length();
if (Len == 0)
return "";
if (XY.Char<1 || XY.Char>Len)
return "";
int start = XY.Char - 1;
if ((start> 0) && !isIdentChar(line[start]))
start--;
if (isIdentChar(line[start])) {
int stop = start;
while ((stop < Len) && isIdentChar(line[stop]))
stop++;
while ((start-1 >=0) && isIdentChar(line[start - 1]))
start--;
if (stop > start)
return line.mid(start,stop-start);
}
}
return "";
}
void SynEdit::setCaretAndSelection(const BufferCoord &ptCaret, const BufferCoord &ptBefore, const BufferCoord &ptAfter)
{
SynSelectionMode vOldMode = mActiveSelectionMode;
@ -4873,6 +4905,27 @@ void SynEdit::ExecuteCommand(SynEditorCommand Command, QChar AChar, void *pData)
}
bool SynEdit::isIdentChar(const QChar &ch)
{
if (mHighlighter) {
return mHighlighter->isIdentChar(ch);
} else {
if (ch == '_') {
return true;
}
if ((ch>='0') && (ch <= '9')) {
return true;
}
if ((ch>='a') && (ch <= 'z')) {
return true;
}
if ((ch>='A') && (ch <= 'Z')) {
return true;
}
return false;
}
}
void SynEdit::paintEvent(QPaintEvent *event)
{
if (mPainterLock>0)

View File

@ -187,6 +187,8 @@ public:
void lockPainter();
void unlockPainter();
bool selAvail() const;
QString WordAtCursor();
QString WordAtRowCol(const BufferCoord& XY);
int charColumns(QChar ch) const;
double dpiFactor() const;
@ -359,6 +361,7 @@ protected:
virtual void ExecuteCommand(SynEditorCommand Command, QChar AChar, void * pData);
private:
bool isIdentChar(const QChar& ch);
void clearAreaList(SynEditingAreaList areaList);
void computeCaret(int X, int Y);
void computeScroll(int X, int Y);

View File

@ -2284,5 +2284,5 @@ void Settings::Debugger::doSave()
void Settings::Debugger::doLoad()
{
mShowCommandLog = boolValue("show_command_log",true);
mShowAnnotations = boolValue("show_annotations",false);
mShowAnnotations = boolValue("show_annotations",true);
}