implemented: watch var handles

This commit is contained in:
Roy Qu 2021-11-25 20:26:43 +08:00
parent 39ab388458
commit 92fcd9b923
10 changed files with 555 additions and 524 deletions

View File

@ -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 Version 0.9.3 For Dev-C++ 7 Beta
- fix: the count in the title of issues view isn't correct - fix: the count in the title of issues view isn't correct
- fix: columns calculation not correct when paint lines containing chinese characters - fix: columns calculation not correct when paint lines containing chinese characters

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,9 @@ Debugger::Debugger(QObject *parent) : QObject(parent)
mReader = nullptr; mReader = nullptr;
mCommandChanged = false; mCommandChanged = false;
mLeftPageIndexBackup = -1; mLeftPageIndexBackup = -1;
connect(mWatchModel, &WatchModel::fetchChildren,
this, &Debugger::fetchVarChildren);
} }
bool Debugger::start() bool Debugger::start()
@ -58,6 +61,7 @@ bool Debugger::start()
tr("Can''t find debugger in : \"%1\"").arg(debuggerPath)); tr("Can''t find debugger in : \"%1\"").arg(debuggerPath));
return false; return false;
} }
mWatchModel->resetAllVarInfos();
mReader = new DebugReader(this); mReader = new DebugReader(this);
mReader->setDebuggerPath(debuggerPath); mReader->setDebuggerPath(debuggerPath);
connect(mReader, &QThread::finished,this,&Debugger::clearUpReader); connect(mReader, &QThread::finished,this,&Debugger::clearUpReader);
@ -81,10 +85,20 @@ bool Debugger::start()
&Debugger::updateRegisterNames); &Debugger::updateRegisterNames);
connect(mReader, &DebugReader::registerValuesUpdated, this, connect(mReader, &DebugReader::registerValuesUpdated, this,
&Debugger::updateRegisterValues); &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, connect(mReader, &DebugReader::inferiorContinued,pMainWindow,
&MainWindow::removeActiveBreakpoints); &MainWindow::removeActiveBreakpoints);
connect(mReader, &DebugReader::inferiorStopped,pMainWindow, connect(mReader, &DebugReader::inferiorStopped,pMainWindow,
&MainWindow::setActiveBreakpoint); &MainWindow::setActiveBreakpoint);
connect(mReader, &DebugReader::inferiorStopped,this,
&Debugger::refreshWatchVars);
mReader->registerInferiorStoppedCommand("-stack-list-frames",""); mReader->registerInferiorStoppedCommand("-stack-list-frames","");
mReader->registerInferiorStoppedCommand("-stack-list-variables", "--all-values"); mReader->registerInferiorStoppedCommand("-stack-list-variables", "--all-values");
@ -110,10 +124,6 @@ void Debugger::clearUpReader()
mReader->deleteLater(); mReader->deleteLater();
mReader=nullptr; mReader=nullptr;
// if WatchVarList.Count = 0 then // nothing worth showing, restore view
// MainForm.LeftPageControl.ActivePageIndex := LeftPageIndexBackup;
// // Close CPU window
if (pMainWindow->cpuDialog()!=nullptr) { if (pMainWindow->cpuDialog()!=nullptr) {
pMainWindow->cpuDialog()->close(); pMainWindow->cpuDialog()->close();
} }
@ -129,9 +139,9 @@ void Debugger::clearUpReader()
mBacktraceModel->clear(); mBacktraceModel->clear();
for(PWatchVar var:mWatchModel->watchVars()) { mWatchModel->clearAllVarInfos();
invalidateWatchVar(var);
} mBreakpointModel->invalidateAllBreakpointNumbers();
pMainWindow->updateEditorActions(); 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... // Don't allow duplicates...
PWatchVar oldVar = mWatchModel->findWatchVar(namein); PWatchVar oldVar = mWatchModel->findWatchVar(expression);
if (oldVar) if (oldVar)
return; return;
PWatchVar var = std::make_shared<WatchVar>(); PWatchVar var = std::make_shared<WatchVar>();
var->parent= nullptr; var->parent= nullptr;
var->expression = namein; var->expression = expression;
var->value = tr("Execute to evaluate"); var->value = tr("Execute to evaluate");
var->numChild = 0; var->numChild = 0;
var->hasMore = false; var->hasMore = false;
var->parent = nullptr;
mWatchModel->addWatchVar(var); mWatchModel->addWatchVar(var);
sendWatchCommand(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; // check if name already exists;
PWatchVar var = mWatchModel->findWatchVar(newname); PWatchVar var = mWatchModel->findWatchVar(newExpr);
if (var) if (var)
return; return;
var = mWatchModel->findWatchVar(oldname); var = mWatchModel->findWatchVar(oldExpr);
if (var) { if (var) {
var->name = newname; if (mExecuting && !var->expression.isEmpty())
if (mExecuting && var->gdbIndex!=-1)
sendRemoveWatchCommand(var); 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) { if (mExecuting) {
sendWatchCommand(var); sendWatchCommand(var);
@ -319,9 +335,16 @@ void Debugger::renameWatchVar(const QString &oldname, const QString &newname)
void Debugger::refreshWatchVars() void Debugger::refreshWatchVars()
{ {
for (PWatchVar var:mWatchModel->watchVars()) { if (mExecuting) {
if (var->gdbIndex == -1) sendAllWatchVarsToDebugger();
sendWatchCommand(var); 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 { } else {
for(const PWatchVar& var:mWatchModel->watchVars()) { for(const PWatchVar& var:mWatchModel->watchVars()) {
sendRemoveWatchCommand(var); sendRemoveWatchCommand(var);
invalidateWatchVar(var);
} }
mWatchModel->clearAllVarInfos();
} }
} }
void Debugger::removeWatchVar(const QModelIndex &index) void Debugger::removeWatchVar(const QModelIndex &index)
{ {
PWatchVar var = mWatchModel->findWatchVar(index);
if (!var)
return;
sendRemoveWatchCommand(var);
mWatchModel->removeWatchVar(index); mWatchModel->removeWatchVar(index);
} }
void Debugger::invalidateAllVars() void Debugger::sendAllWatchVarsToDebugger()
{
mReader->setInvalidateAllVars(true);
}
void Debugger::sendAllWatchvarsToDebugger()
{ {
for (PWatchVar var:mWatchModel->watchVars()) { for (PWatchVar var:mWatchModel->watchVars()) {
if (var->name.isEmpty())
sendWatchCommand(var); sendWatchCommand(var);
} }
} }
void Debugger::invalidateWatchVar(const QString &name) PWatchVar Debugger::findWatchVar(const QString &expression)
{ {
PWatchVar var = mWatchModel->findWatchVar(name); return mWatchModel->findWatchVar(expression);
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);
} }
//void Debugger::notifyWatchVarUpdated(PWatchVar var) //void Debugger::notifyWatchVarUpdated(PWatchVar var)
//{ //{
// mWatchModel->notifyUpdated(var); // mWatchModel->notifyUpdated(var);
//} //}
void Debugger::notifyBeforeProcessWatchVar()
{
mWatchModel->beginUpdate();
}
void Debugger::notifyAfterProcessWatchVar()
{
mWatchModel->endUpdate();
}
BacktraceModel* Debugger::backtraceModel() BacktraceModel* Debugger::backtraceModel()
{ {
return mBacktraceModel; return mBacktraceModel;
@ -413,7 +398,7 @@ BreakpointModel *Debugger::breakpointModel()
void Debugger::sendWatchCommand(PWatchVar var) void Debugger::sendWatchCommand(PWatchVar var)
{ {
sendCommand("-var-carete", QString(" - %1").arg(var->expression)); sendCommand("-var-create", var->expression);
} }
void Debugger::sendRemoveWatchCommand(PWatchVar var) void Debugger::sendRemoveWatchCommand(PWatchVar var)
@ -587,7 +572,6 @@ DebugReader::DebugReader(Debugger* debugger, QObject *parent) : QThread(parent),
mDebugger = debugger; mDebugger = debugger;
mProcess = nullptr; mProcess = nullptr;
mCmdRunning = false; mCmdRunning = false;
mInvalidateAllVars = false;
} }
void DebugReader::postCommand(const QString &Command, const QString &Params, void DebugReader::postCommand(const QString &Command, const QString &Params,
@ -740,6 +724,15 @@ void DebugReader::processResult(const QByteArray &result)
case GDBMIResultType::RegisterValues: case GDBMIResultType::RegisterValues:
handleRegisterValue(multiValues["register-values"].array()); handleRegisterValue(multiValues["register-values"].array());
return; 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 // Only update once per update at most
//WatchView.Items.BeginUpdate; //WatchView.Items.BeginUpdate;
if (mInvalidateAllVars) {
//invalidate all vars when there's first output
mDebugger->removeWatchVars(false);
mInvalidateAllVars = false;
}
emit parseStarted(); emit parseStarted();
mConsoleOutput.clear(); 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<PWatchVar> varStack;
int i=0;
while (i<tokens.length()) {
QString token = tokens[i];
QChar ch = token[0];
if (ch =='_' || (ch>='a' && ch<='z')
|| (ch>='A' && ch<='Z') || (ch>127)) {
//is identifier,create new child node
PWatchVar newVar = std::make_shared<WatchVar>();
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<WatchVar>();
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<WatchVar>();
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<WatchVar>();
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<WatchVar>();
// 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<WatchVar>();
// 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<WatchVar>();
// newVar->parent = parentVar.get();
// newVar->name = "";
// newVar->text = nodeText;
// newVar->gdbIndex = -1;
// parentVar->children.append(newVar);
// }
// }
// }
// TODO: remember expansion state
}
void DebugReader::runNextCmd() void DebugReader::runNextCmd()
{ {
QMutexLocker locker(&mCmdQueueMutex); QMutexLocker locker(&mCmdQueueMutex);
@ -1100,10 +903,19 @@ void DebugReader::runNextCmd()
emit cmdStarted(); emit cmdStarted();
QByteArray s; QByteArray s;
QByteArray params;
s=pCmd->command.toLocal8Bit(); s=pCmd->command.toLocal8Bit();
if (!pCmd->params.isEmpty()) { 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"; s+= "\n";
if (mProcess->write(s)<0) { if (mProcess->write(s)<0) {
emit writeToDebugFailed(); emit writeToDebugFailed();
@ -1113,9 +925,9 @@ void DebugReader::runNextCmd()
if (pSettings->debugger().enableDebugConsole() ) { if (pSettings->debugger().enableDebugConsole() ) {
//update debug console //update debug console
if (!pSettings->debugger().showDetailLog()) { if (!pSettings->debugger().showDetailLog()) {
emit changeDebugConsoleLastLine(pCmd->command + ' ' + pCmd->params); emit changeDebugConsoleLastLine(pCmd->command + ' ' + params);
} else { } else {
emit changeDebugConsoleLastLine(pCmd->command + ' ' + pCmd->params); emit changeDebugConsoleLastLine(pCmd->command + ' ' + params);
} }
} }
} }
@ -1309,6 +1121,62 @@ void DebugReader::handleRegisterValue(const QList<GDBMIResultParser::ParseValue>
emit registerValuesUpdated(result); 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<GDBMIResultParser::ParseValue> 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<GDBMIResultParser::ParseValue> &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) QByteArray DebugReader::removeToken(const QByteArray &line)
{ {
int p=0; int p=0;
@ -1374,16 +1242,6 @@ bool DebugReader::processExited() const
return mProcessExited; return mProcessExited;
} }
bool DebugReader::invalidateAllVars() const
{
return mInvalidateAllVars;
}
void DebugReader::setInvalidateAllVars(bool invalidateAllVars)
{
mInvalidateAllVars = invalidateAllVars;
}
QString DebugReader::debuggerPath() const QString DebugReader::debuggerPath() const
{ {
return mDebuggerPath; return mDebuggerPath;
@ -1810,7 +1668,6 @@ QVariant WatchModel::data(const QModelIndex &index, int role) const
WatchVar* item = static_cast<WatchVar*>(index.internalPointer()); WatchVar* item = static_cast<WatchVar*>(index.internalPointer());
switch (role) { switch (role) {
case Qt::DisplayRole: case Qt::DisplayRole:
//qDebug()<<"item->text:"<<item->text;
switch(index.column()) { switch(index.column()) {
case 0: case 0:
return item->expression; return item->expression;
@ -1827,7 +1684,6 @@ QModelIndex WatchModel::index(int row, int column, const QModelIndex &parent) co
{ {
if (!hasIndex(row,column,parent)) if (!hasIndex(row,column,parent))
return QModelIndex(); return QModelIndex();
WatchVar* parentItem; WatchVar* parentItem;
PWatchVar pChild; PWatchVar pChild;
if (!parent.isValid()) { if (!parent.isValid()) {
@ -1897,9 +1753,9 @@ void WatchModel::addWatchVar(PWatchVar watchVar)
return; return;
} }
} }
this->beginInsertRows(QModelIndex(),mWatchVars.size(),mWatchVars.size()); beginInsertRows(QModelIndex(),mWatchVars.count(),mWatchVars.count());
mWatchVars.append(watchVar); mWatchVars.append(watchVar);
this->endInsertRows(); endInsertRows();
} }
void WatchModel::removeWatchVar(const QString &express) void WatchModel::removeWatchVar(const QString &express)
@ -1909,6 +1765,8 @@ void WatchModel::removeWatchVar(const QString &express)
if (express == var->expression) { if (express == var->expression) {
this->beginResetModel(); this->beginResetModel();
//this->beginRemoveRows(QModelIndex(),i,i); //this->beginRemoveRows(QModelIndex(),i,i);
if (mVarIndex.contains(var->name))
mVarIndex.remove(var->name);
mWatchVars.removeAt(i); mWatchVars.removeAt(i);
//this->endRemoveRows(); //this->endRemoveRows();
this->endResetModel(); this->endResetModel();
@ -1920,6 +1778,9 @@ void WatchModel::removeWatchVar(const QModelIndex &index)
{ {
int r=index.row(); int r=index.row();
this->beginRemoveRows(QModelIndex(),r,r); this->beginRemoveRows(QModelIndex(),r,r);
PWatchVar var = mWatchVars[r];
if (mVarIndex.contains(var->name))
mVarIndex.remove(var->name);
mWatchVars.removeAt(r); mWatchVars.removeAt(r);
this->endRemoveRows(); this->endRemoveRows();
} }
@ -1936,24 +1797,124 @@ const QList<PWatchVar> &WatchModel::watchVars()
return mWatchVars; 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) { for (PWatchVar var:mWatchVars) {
if (name == var->name) { if (expr == var->expression) {
return var; return var;
} }
} }
return PWatchVar(); return PWatchVar();
} }
PWatchVar WatchModel::findWatchVar(int gdbIndex) void WatchModel::resetAllVarInfos()
{ {
for (PWatchVar var:mWatchVars) { beginResetModel();
if (gdbIndex == var->gdbIndex) { foreach (PWatchVar var, mWatchVars) {
return var; var->name.clear();
var->value = tr("Not Valid");
var->numChild = 0;
var->hasMore = false;
var->type.clear();
var->children.clear();
} }
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;
} }
return PWatchVar(); }
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<WatchVar>();
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() void WatchModel::beginUpdate()
@ -2036,6 +1997,7 @@ void WatchModel::load(const QString &filename)
var->value = tr("Execute to evaluate"); var->value = tr("Execute to evaluate");
var->numChild = 0; var->numChild = 0;
var->hasMore=false; var->hasMore=false;
var->parent = nullptr;
addWatchVar(var); 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;i<pVar->parent->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<mWatchVars.count();i++) {
if (mWatchVars[i].get() == pVar) {
row = i;
break;
}
}
if (row<0)
return QModelIndex();
return createIndex(row,0,pVar);
}
}
QVariant WatchModel::headerData(int section, Qt::Orientation orientation, int role) const QVariant WatchModel::headerData(int section, Qt::Orientation orientation, int role) const
{ {
@ -2063,7 +2060,13 @@ QVariant WatchModel::headerData(int section, Qt::Orientation orientation, int ro
void WatchModel::fetchMore(const QModelIndex &parent) void WatchModel::fetchMore(const QModelIndex &parent)
{ {
//todo if (!parent.isValid()) {
return;
}
WatchVar* item = static_cast<WatchVar*>(parent.internalPointer());
item->hasMore = false;
item->numChild = item->children.count();
emit fetchChildren(item->name);
} }
bool WatchModel::canFetchMore(const QModelIndex &parent) const bool WatchModel::canFetchMore(const QModelIndex &parent) const
@ -2072,13 +2075,13 @@ bool WatchModel::canFetchMore(const QModelIndex &parent) const
return false; return false;
} }
WatchVar* item = static_cast<WatchVar*>(parent.internalPointer()); WatchVar* item = static_cast<WatchVar*>(parent.internalPointer());
return item->numChild>item->children.count(); return item->numChild>item->children.count() || item->hasMore;
} }
bool WatchModel::hasChildren(const QModelIndex &parent) const bool WatchModel::hasChildren(const QModelIndex &parent) const
{ {
if (!parent.isValid()) { if (!parent.isValid()) {
return false; return true;
} }
WatchVar* item = static_cast<WatchVar*>(parent.internalPointer()); WatchVar* item = static_cast<WatchVar*>(parent.internalPointer());
return item->numChild>0; return item->numChild>0;

View File

@ -131,34 +131,51 @@ public:
QModelIndex index(int row, int column, QModelIndex index(int row, int column,
const QModelIndex &parent = QModelIndex()) const override; const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &index) 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 rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(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 addWatchVar(PWatchVar watchVar);
void removeWatchVar(const QString& expression); void removeWatchVar(const QString& expression);
void removeWatchVar(const QModelIndex& index); void removeWatchVar(const QModelIndex& index);
void clear(); void clear();
const QList<PWatchVar>& watchVars(); const QList<PWatchVar>& watchVars();
PWatchVar findWatchVar(const QString& name); PWatchVar findWatchVar(const QModelIndex& index);
PWatchVar findWatchVar(int gdbIndex); PWatchVar findWatchVar(const QString& expr);
void resetAllVarInfos();
void clearAllVarInfos();
void beginUpdate(); void beginUpdate();
void endUpdate(); void endUpdate();
void notifyUpdated(PWatchVar var); void notifyUpdated(PWatchVar var);
void save(const QString& filename); void save(const QString& filename);
void load(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: private:
QList<PWatchVar> mWatchVars; QList<PWatchVar> mWatchVars;
QHash<QString,PWatchVar> mVarIndex;
int mUpdateCount; 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); PBreakpoint breakpointAt(int line, const Editor* editor, int &index);
void setBreakPointCondition(int index, const QString& condition); void setBreakPointCondition(int index, const QString& condition);
void sendAllBreakpointsToDebugger(); void sendAllBreakpointsToDebugger();
void validateBreakpoint(int line, const QString& filename, int number);
void invalidateAllBreakpoints();
//watch vars //watch vars
void addWatchVar(const QString& namein); void addWatchVar(const QString& expression);
// void removeWatchVar(nodein: TTreeNode); overload; void modifyWatchVarExpression(const QString& oldExpr, const QString& newExpr);
void renameWatchVar(const QString& oldname, const QString& newname);
void refreshWatchVars();
void removeWatchVars(bool deleteparent); void removeWatchVars(bool deleteparent);
void removeWatchVar(const QModelIndex& index); void removeWatchVar(const QModelIndex& index);
void invalidateAllVars(); void sendAllWatchVarsToDebugger();
void sendAllWatchvarsToDebugger(); PWatchVar findWatchVar(const QString& expression);
void invalidateWatchVar(const QString& name);
void invalidateWatchVar(PWatchVar var);
PWatchVar findWatchVar(const QString& name);
// void notifyWatchVarUpdated(PWatchVar var); // void notifyWatchVarUpdated(PWatchVar var);
void notifyBeforeProcessWatchVar();
void notifyAfterProcessWatchVar();
BacktraceModel* backtraceModel(); BacktraceModel* backtraceModel();
BreakpointModel* breakpointModel(); BreakpointModel* breakpointModel();
@ -246,7 +254,8 @@ private slots:
void clearUpReader(); void clearUpReader();
void updateRegisterNames(const QStringList& registerNames); void updateRegisterNames(const QStringList& registerNames);
void updateRegisterValues(const QHash<int,QString>& values); void updateRegisterValues(const QHash<int,QString>& values);
void refreshWatchVars();
void fetchVarChildren(const QString& varName);
private: private:
bool mExecuting; bool mExecuting;
bool mCommandChanged; bool mCommandChanged;
@ -272,9 +281,6 @@ public:
bool commandRunning(); bool commandRunning();
void waitStart(); void waitStart();
bool invalidateAllVars() const;
void setInvalidateAllVars(bool invalidateAllVars);
bool inferiorPaused() const; bool inferiorPaused() const;
bool processExited() const; bool processExited() const;
@ -332,11 +338,24 @@ signals:
void disassemblyUpdate(const QString& filename, const QString& funcName, const QStringList& result); void disassemblyUpdate(const QString& filename, const QString& funcName, const QStringList& result);
void registerNamesUpdated(const QStringList& registerNames); void registerNamesUpdated(const QStringList& registerNames);
void registerValuesUpdated(const QHash<int,QString>& values); void registerValuesUpdated(const QHash<int,QString>& 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: private:
void clearCmdQueue(); void clearCmdQueue();
QString processEvalOutput();
void processWatchOutput(PWatchVar WatchVar);
void runNextCmd(); void runNextCmd();
QStringList tokenize(const QString& s); QStringList tokenize(const QString& s);
@ -348,6 +367,9 @@ private:
void handleMemory(const QList<GDBMIResultParser::ParseValue> & rows); void handleMemory(const QList<GDBMIResultParser::ParseValue> & rows);
void handleRegisterNames(const QList<GDBMIResultParser::ParseValue> & names); void handleRegisterNames(const QList<GDBMIResultParser::ParseValue> & names);
void handleRegisterValue(const QList<GDBMIResultParser::ParseValue> & values); void handleRegisterValue(const QList<GDBMIResultParser::ParseValue> & values);
void handleCreateVar(const GDBMIResultParser::ParseObject& multiVars);
void handleListVarChildren(const GDBMIResultParser::ParseObject& multiVars);
void handleUpdateVarValue(const QList<GDBMIResultParser::ParseValue> &changes);
void processConsoleOutput(const QByteArray& line); void processConsoleOutput(const QByteArray& line);
void processResult(const QByteArray& result); void processResult(const QByteArray& result);
void processExecAsyncRecord(const QByteArray& line); void processExecAsyncRecord(const QByteArray& line);
@ -362,7 +384,6 @@ private:
QRecursiveMutex mCmdQueueMutex; QRecursiveMutex mCmdQueueMutex;
QSemaphore mStartSemaphore; QSemaphore mStartSemaphore;
QQueue<PDebugCommand> mCmdQueue; QQueue<PDebugCommand> mCmdQueue;
bool mInvalidateAllVars;
//fOnInvalidateAllVars: TInvalidateAllVarsEvent; //fOnInvalidateAllVars: TInvalidateAllVarsEvent;
bool mCmdRunning; bool mCmdRunning;

View File

@ -18,6 +18,9 @@ GDBMIResultParser::GDBMIResultParser()
mResultTypes.insert("-data-read-memory",GDBMIResultType::Memory); mResultTypes.insert("-data-read-memory",GDBMIResultType::Memory);
mResultTypes.insert("-data-list-register-names",GDBMIResultType::RegisterNames); mResultTypes.insert("-data-list-register-names",GDBMIResultType::RegisterNames);
mResultTypes.insert("-data-list-register-values",GDBMIResultType::RegisterValues); 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) bool GDBMIResultParser::parse(const QByteArray &record, const QString& command, GDBMIResultType &type, ParseObject& multiValues)
@ -290,6 +293,8 @@ bool GDBMIResultParser::isNameChar(char ch)
{ {
if (ch=='-') if (ch=='-')
return true; return true;
if (ch=='_')
return true;
if (ch>='a' && ch<='z') if (ch>='a' && ch<='z')
return true; return true;
if (ch>='A' && ch<='Z') if (ch>='A' && ch<='Z')
@ -315,19 +320,16 @@ void GDBMIResultParser::skipSpaces(const char *&p)
const QByteArray &GDBMIResultParser::ParseValue::value() const const QByteArray &GDBMIResultParser::ParseValue::value() const
{ {
Q_ASSERT(mType == ParseValueType::Value);
return mValue; return mValue;
} }
const QList<::GDBMIResultParser::ParseValue> &GDBMIResultParser::ParseValue::array() const const QList<::GDBMIResultParser::ParseValue> &GDBMIResultParser::ParseValue::array() const
{ {
Q_ASSERT(mType == ParseValueType::Array);
return mArray; return mArray;
} }
const GDBMIResultParser::ParseObject &GDBMIResultParser::ParseValue::object() const const GDBMIResultParser::ParseObject &GDBMIResultParser::ParseValue::object() const
{ {
Q_ASSERT(mType == ParseValueType::Object);
return mObject; return mObject;
} }

View File

@ -19,8 +19,9 @@ enum class GDBMIResultType {
RegisterNames, RegisterNames,
RegisterValues, RegisterValues,
Memory, Memory,
VariableInfo, CreateVar,
ListVarChildren,
UpdateVarValue
}; };

View File

@ -1444,10 +1444,6 @@ void MainWindow::debug()
includeOrSkipDirs(compilerSet->defaultCppIncludeDirs(),true); 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(); mDebugger->sendAllBreakpointsToDebugger();
// Run the debugger // Run the debugger
@ -1677,10 +1673,10 @@ void MainWindow::includeOrSkipDirs(const QStringList &dirs, bool skip)
foreach (QString dir,dirs) { foreach (QString dir,dirs) {
QString dirName = dir.replace('\\','/'); QString dirName = dir.replace('\\','/');
if (skip) { if (skip) {
// mDebugger->sendCommand( mDebugger->sendCommand(
// "skip", "skip",
// QString("-gfi \"%1/%2\"") QString("-gfi \"%1/%2\"")
// .arg(dirName,"*.*")); .arg(dirName,"*.*"));
} else { } else {
mDebugger->sendCommand( mDebugger->sendCommand(
"-environment-directory", "-environment-directory",
@ -4001,7 +3997,6 @@ void MainWindow::on_actionStep_Over_triggered()
{ {
if (mDebugger->executing()) { if (mDebugger->executing()) {
//WatchView.Items.BeginUpdate(); //WatchView.Items.BeginUpdate();
mDebugger->invalidateAllVars();
mDebugger->sendCommand("-exec-next", ""); mDebugger->sendCommand("-exec-next", "");
} }
} }
@ -4010,7 +4005,6 @@ void MainWindow::on_actionStep_Into_triggered()
{ {
if (mDebugger->executing()) { if (mDebugger->executing()) {
//WatchView.Items.BeginUpdate(); //WatchView.Items.BeginUpdate();
mDebugger->invalidateAllVars();
mDebugger->sendCommand("-exec-step", ""); mDebugger->sendCommand("-exec-step", "");
} }
@ -4020,7 +4014,6 @@ void MainWindow::on_actionStep_Out_triggered()
{ {
if (mDebugger->executing()) { if (mDebugger->executing()) {
//WatchView.Items.BeginUpdate(); //WatchView.Items.BeginUpdate();
mDebugger->invalidateAllVars();
mDebugger->sendCommand("-exec-finish", ""); mDebugger->sendCommand("-exec-finish", "");
} }
@ -4032,7 +4025,6 @@ void MainWindow::on_actionRun_To_Cursor_triggered()
Editor *e=mEditorList->getEditor(); Editor *e=mEditorList->getEditor();
if (e!=nullptr) { if (e!=nullptr) {
//WatchView.Items.BeginUpdate(); //WatchView.Items.BeginUpdate();
mDebugger->invalidateAllVars();
mDebugger->sendCommand("-exec-until", QString("\"%1\":%2") mDebugger->sendCommand("-exec-until", QString("\"%1\":%2")
.arg(e->filename()) .arg(e->filename())
.arg(e->caretY())); .arg(e->caretY()));
@ -4045,7 +4037,6 @@ void MainWindow::on_actionContinue_triggered()
{ {
if (mDebugger->executing()) { if (mDebugger->executing()) {
//WatchView.Items.BeginUpdate(); //WatchView.Items.BeginUpdate();
mDebugger->invalidateAllVars();
mDebugger->sendCommand("-exec-continue", ""); mDebugger->sendCommand("-exec-continue", "");
} }
} }

View File

@ -85,7 +85,7 @@
<enum>QTabWidget::West</enum> <enum>QTabWidget::West</enum>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>3</number> <number>1</number>
</property> </property>
<property name="usesScrollButtons"> <property name="usesScrollButtons">
<bool>true</bool> <bool>true</bool>
@ -174,7 +174,7 @@
<bool>false</bool> <bool>false</bool>
</property> </property>
<attribute name="headerDefaultSectionSize"> <attribute name="headerDefaultSectionSize">
<number>50</number> <number>100</number>
</attribute> </attribute>
</widget> </widget>
</item> </item>

View File

@ -2,6 +2,6 @@
#define VERSION_H #define VERSION_H
#include <QObject> #include <QObject>
#define DEVCPP_VERSION "beta.0.9.3" #define DEVCPP_VERSION "beta.0.10.0"
#endif // VERSION_H #endif // VERSION_H