forked from qt-creator/qt-creator
debugger: rework WatchModel
It's one model for all locals, watch, return, tooltip and inspector data. This allows more streamlined code paths and better isolation of the model data from the WatchHandler. WatchItems are now registered in a hash indexed by iname, so inames can be used as the primary handle to watch data in the WatchHandler interface. Change-Id: Idac0a808b5d785307496d1de4198a1f2e9ce3880 Reviewed-by: Aurindam Jana <aurindam.jana@nokia.com>
This commit is contained in:
@@ -2397,6 +2397,14 @@ def qdump__Debugger__Internal__GdbMi(d, value):
|
||||
d.putByteArrayValue(value["m_data"])
|
||||
d.putPlainChildren(value)
|
||||
|
||||
def qdump__Debugger__Internal__WatchData(d, value):
|
||||
d.putByteArrayValue(value["iname"])
|
||||
d.putPlainChildren(value)
|
||||
|
||||
def qdump__Debugger__Internal__WatchItem(d, value):
|
||||
d.putByteArrayValue(value["iname"])
|
||||
d.putPlainChildren(value)
|
||||
|
||||
def qdump__CPlusPlus__ByteArrayRef(d, value):
|
||||
d.putValue(encodeCharArray(value["m_start"], 100, value["m_length"]),
|
||||
Hex2EncodedLatin1)
|
||||
|
@@ -98,6 +98,12 @@ enum { debugSourceMapping = 0 };
|
||||
enum { debugWatches = 0 };
|
||||
enum { debugBreakpoints = 0 };
|
||||
|
||||
enum HandleLocalsFlags
|
||||
{
|
||||
PartialLocalsUpdate = 0x1,
|
||||
LocalsUpdateForNewFrame = 0x2
|
||||
};
|
||||
|
||||
#if 0
|
||||
# define STATE_DEBUG(state, func, line, notifyFunc) qDebug("%s in %s at %s:%d", notifyFunc, stateName(state), func, line);
|
||||
#else
|
||||
@@ -550,18 +556,16 @@ bool CdbEngine::setToolTipExpression(const QPoint &mousePos,
|
||||
// Can this be found as a local variable?
|
||||
const QByteArray localsPrefix(localsPrefixC);
|
||||
QByteArray iname = localsPrefix + exp.toAscii();
|
||||
QModelIndex index = watchHandler()->itemIndex(iname);
|
||||
if (!index.isValid()) {
|
||||
if (!watchHandler()->hasItem(iname)) {
|
||||
// Nope, try a 'local.this.m_foo'.
|
||||
exp.prepend(QLatin1String("this."));
|
||||
iname.insert(localsPrefix.size(), "this.");
|
||||
index = watchHandler()->itemIndex(iname);
|
||||
if (!index.isValid())
|
||||
if (!watchHandler()->hasItem(iname))
|
||||
return false;
|
||||
}
|
||||
DebuggerToolTipWidget *tw = new DebuggerToolTipWidget;
|
||||
tw->setContext(context);
|
||||
tw->setDebuggerModel(LocalsWatch);
|
||||
tw->setDebuggerModel(LocalsType);
|
||||
tw->setExpression(exp);
|
||||
tw->acquireEngine(this);
|
||||
DebuggerToolTipManager::instance()->showToolTip(mousePos, editor, tw);
|
||||
@@ -1048,7 +1052,7 @@ void CdbEngine::handleAddWatch(const CdbExtensionCommandPtr &reply)
|
||||
updateLocalVariable(item.iname);
|
||||
} else {
|
||||
item.setError(tr("Unable to add expression"));
|
||||
watchHandler()->insertData(item);
|
||||
watchHandler()->insertIncompleteData(item);
|
||||
showMessage(QString::fromLatin1("Unable to add watch item '%1'/'%2': %3").
|
||||
arg(QString::fromLatin1(item.iname), QString::fromLatin1(item.exp),
|
||||
QString::fromLocal8Bit(reply->errorMessage)), LogError);
|
||||
@@ -1086,7 +1090,10 @@ void CdbEngine::updateLocalVariable(const QByteArray &iname)
|
||||
str << blankSeparator << stackFrame;
|
||||
}
|
||||
str << blankSeparator << iname;
|
||||
postExtensionCommand(isWatch ? "watches" : "locals", localsArguments, 0, &CdbEngine::handleLocals);
|
||||
postExtensionCommand(isWatch ? "watches" : "locals",
|
||||
localsArguments, 0,
|
||||
&CdbEngine::handleLocals,
|
||||
0, QVariant(int(PartialLocalsUpdate)));
|
||||
}
|
||||
|
||||
bool CdbEngine::hasCapability(unsigned cap) const
|
||||
@@ -1465,8 +1472,7 @@ void CdbEngine::activateFrame(int index)
|
||||
stackHandler()->setCurrentIndex(index);
|
||||
const bool showAssembler = !frames.at(index).isUsable();
|
||||
if (showAssembler) { // Assembly code: Clean out model and force instruction mode.
|
||||
watchHandler()->beginCycle();
|
||||
watchHandler()->endCycle();
|
||||
watchHandler()->removeAllData();
|
||||
QAction *assemblerAction = theAssemblerAction();
|
||||
if (assemblerAction->isChecked()) {
|
||||
gotoLocation(frame);
|
||||
@@ -1485,14 +1491,12 @@ void CdbEngine::updateLocals(bool forNewStackFrame)
|
||||
|
||||
const int frameIndex = stackHandler()->currentIndex();
|
||||
if (frameIndex < 0) {
|
||||
watchHandler()->beginCycle();
|
||||
watchHandler()->endCycle();
|
||||
watchHandler()->removeAllData();
|
||||
return;
|
||||
}
|
||||
const StackFrame frame = stackHandler()->currentFrame();
|
||||
if (!frame.isUsable()) {
|
||||
watchHandler()->beginCycle();
|
||||
watchHandler()->endCycle();
|
||||
watchHandler()->removeAllData();
|
||||
return;
|
||||
}
|
||||
/* Watchers: Forcibly discard old symbol group as switching from
|
||||
@@ -1542,9 +1546,11 @@ void CdbEngine::updateLocals(bool forNewStackFrame)
|
||||
}
|
||||
|
||||
// Required arguments: frame
|
||||
const int flags = forNewStackFrame ? LocalsUpdateForNewFrame : 0;
|
||||
str << blankSeparator << frameIndex;
|
||||
watchHandler()->beginCycle();
|
||||
postExtensionCommand("locals", arguments, 0, &CdbEngine::handleLocals, 0, QVariant(forNewStackFrame));
|
||||
postExtensionCommand("locals", arguments, 0,
|
||||
&CdbEngine::handleLocals, 0,
|
||||
QVariant(flags));
|
||||
}
|
||||
|
||||
void CdbEngine::selectThread(int index)
|
||||
@@ -1925,6 +1931,9 @@ void CdbEngine::handleRegisters(const CdbExtensionCommandPtr &reply)
|
||||
|
||||
void CdbEngine::handleLocals(const CdbExtensionCommandPtr &reply)
|
||||
{
|
||||
const int flags = reply->cookie.toInt();
|
||||
if (!(flags & PartialLocalsUpdate))
|
||||
watchHandler()->removeAllData();
|
||||
if (reply->success) {
|
||||
QList<WatchData> watchData;
|
||||
GdbMi root;
|
||||
@@ -1940,16 +1949,14 @@ void CdbEngine::handleLocals(const CdbExtensionCommandPtr &reply)
|
||||
dummy.name = QLatin1String(child.findChild("name").data());
|
||||
parseWatchData(watchHandler()->expandedINames(), dummy, child, &watchData);
|
||||
}
|
||||
watchHandler()->insertBulkData(watchData);
|
||||
watchHandler()->endCycle();
|
||||
watchHandler()->insertData(watchData);
|
||||
if (debugLocals) {
|
||||
QDebug nsp = qDebug().nospace();
|
||||
nsp << "Obtained " << watchData.size() << " items:\n";
|
||||
foreach (const WatchData &wd, watchData)
|
||||
nsp << wd.toString() <<'\n';
|
||||
}
|
||||
const bool forNewStackFrame = reply->cookie.toBool();
|
||||
if (forNewStackFrame)
|
||||
if (flags & LocalsUpdateForNewFrame)
|
||||
emit stackFrameCompleted();
|
||||
} else {
|
||||
showMessage(QString::fromLatin1(reply->errorMessage), LogWarning);
|
||||
|
@@ -85,7 +85,7 @@ public:
|
||||
virtual QVariant configValue(const QString &name) const = 0;
|
||||
virtual void setConfigValue(const QString &name, const QVariant &value) = 0;
|
||||
virtual void updateState(DebuggerEngine *engine) = 0;
|
||||
virtual void updateWatchersWindow() = 0;
|
||||
virtual void updateWatchersWindow(bool showWatch, bool showReturn) = 0;
|
||||
virtual void showQtDumperLibraryWarning(const QString &details) = 0;
|
||||
virtual QIcon locationMarkIcon() const = 0;
|
||||
virtual const CPlusPlus::Snapshot &cppCodeModelSnapshot() const = 0;
|
||||
|
@@ -491,42 +491,32 @@ QAbstractItemModel *DebuggerEngine::threadsModel() const
|
||||
|
||||
QAbstractItemModel *DebuggerEngine::localsModel() const
|
||||
{
|
||||
QAbstractItemModel *model = watchHandler()->model(LocalsWatch);
|
||||
if (model->objectName().isEmpty()) // Make debugging easier.
|
||||
model->setObjectName(objectName() + QLatin1String("LocalsModel"));
|
||||
return model;
|
||||
return watchHandler()->model();
|
||||
}
|
||||
|
||||
QAbstractItemModel *DebuggerEngine::watchersModel() const
|
||||
{
|
||||
QAbstractItemModel *model = watchHandler()->model(WatchersWatch);
|
||||
if (model->objectName().isEmpty()) // Make debugging easier.
|
||||
model->setObjectName(objectName() + QLatin1String("WatchersModel"));
|
||||
return model;
|
||||
return watchHandler()->model();
|
||||
}
|
||||
|
||||
QAbstractItemModel *DebuggerEngine::returnModel() const
|
||||
{
|
||||
QAbstractItemModel *model = watchHandler()->model(ReturnWatch);
|
||||
if (model->objectName().isEmpty()) // Make debugging easier.
|
||||
model->setObjectName(objectName() + QLatin1String("ReturnModel"));
|
||||
return model;
|
||||
return watchHandler()->model();
|
||||
}
|
||||
|
||||
QAbstractItemModel *DebuggerEngine::inspectorModel() const
|
||||
{
|
||||
QAbstractItemModel *model = watchHandler()->model(InspectWatch);
|
||||
if (model->objectName().isEmpty()) // Make debugging easier.
|
||||
model->setObjectName(objectName() + QLatin1String("InspectorModel"));
|
||||
return model;
|
||||
return watchHandler()->model();
|
||||
}
|
||||
|
||||
QAbstractItemModel *DebuggerEngine::toolTipsModel() const
|
||||
{
|
||||
QAbstractItemModel *model = watchHandler()->model(TooltipsWatch);
|
||||
if (model->objectName().isEmpty()) // Make debugging easier.
|
||||
model->setObjectName(objectName() + QLatin1String("TooltipsModel"));
|
||||
return model;
|
||||
return watchHandler()->model();
|
||||
}
|
||||
|
||||
QAbstractItemModel *DebuggerEngine::watchModel() const
|
||||
{
|
||||
return watchHandler()->model();
|
||||
}
|
||||
|
||||
QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
|
||||
|
@@ -229,11 +229,12 @@ public:
|
||||
virtual QAbstractItemModel *registerModel() const;
|
||||
virtual QAbstractItemModel *stackModel() const;
|
||||
virtual QAbstractItemModel *threadsModel() const;
|
||||
virtual QAbstractItemModel *localsModel() const;
|
||||
virtual QAbstractItemModel *watchersModel() const;
|
||||
virtual QAbstractItemModel *returnModel() const;
|
||||
virtual QAbstractItemModel *inspectorModel() const;
|
||||
virtual QAbstractItemModel *toolTipsModel() const;
|
||||
virtual QAbstractItemModel *localsModel() const; // Deprecated, FIXME: use watchModel
|
||||
virtual QAbstractItemModel *watchersModel() const; // Deprecated, FIXME: use watchModel
|
||||
virtual QAbstractItemModel *returnModel() const; // Deprecated, FIXME: use watchModel
|
||||
virtual QAbstractItemModel *inspectorModel() const; // Deprecated, FIXME: use watchModel
|
||||
virtual QAbstractItemModel *toolTipsModel() const; // Deprecated, FIXME: use watchModel
|
||||
virtual QAbstractItemModel *watchModel() const;
|
||||
virtual QAbstractItemModel *sourceFilesModel() const;
|
||||
virtual QAbstractItemModel *qtMessageLogModel() const;
|
||||
|
||||
|
@@ -815,7 +815,7 @@ public slots:
|
||||
void fontSettingsChanged(const TextEditor::FontSettings &settings);
|
||||
|
||||
void updateState(DebuggerEngine *engine);
|
||||
void updateWatchersWindow();
|
||||
void updateWatchersWindow(bool showWatch, bool showReturn);
|
||||
void onCurrentProjectChanged(ProjectExplorer::Project *project);
|
||||
|
||||
void sessionLoaded();
|
||||
@@ -2238,12 +2238,10 @@ void DebuggerPluginPrivate::setInitialState()
|
||||
m_qtMessageLogWindow->setEnabled(true);
|
||||
}
|
||||
|
||||
void DebuggerPluginPrivate::updateWatchersWindow()
|
||||
void DebuggerPluginPrivate::updateWatchersWindow(bool showWatch, bool showReturn)
|
||||
{
|
||||
m_watchersWindow->setVisible(
|
||||
m_watchersWindow->model()->rowCount(QModelIndex()) > 0);
|
||||
m_returnWindow->setVisible(
|
||||
m_returnWindow->model()->rowCount(QModelIndex()) > 0);
|
||||
m_watchersWindow->setVisible(showWatch);
|
||||
m_returnWindow->setVisible(showReturn);
|
||||
}
|
||||
|
||||
void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
|
||||
@@ -2254,8 +2252,7 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
|
||||
QTC_ASSERT(!engine->isSlaveEngine(), return);
|
||||
|
||||
m_threadBox->setCurrentIndex(engine->threadsHandler()->currentThread());
|
||||
|
||||
updateWatchersWindow();
|
||||
engine->watchHandler()->updateWatchersWindow();
|
||||
|
||||
const DebuggerState state = engine->state();
|
||||
//showMessage(QString("PLUGIN SET STATE: ")
|
||||
|
@@ -230,7 +230,6 @@ QDataStream &operator<<(QDataStream &stream, const WatchData &wd)
|
||||
stream << wd.address;
|
||||
stream << wd.size;
|
||||
stream << wd.hasChildren;
|
||||
stream << wd.generation;
|
||||
stream << wd.valueEnabled;
|
||||
stream << wd.valueEditable;
|
||||
stream << wd.error;
|
||||
@@ -256,7 +255,6 @@ QDataStream &operator>>(QDataStream &stream, WatchData &wd)
|
||||
stream >> wd.address;
|
||||
stream >> wd.size;
|
||||
stream >> wd.hasChildren;
|
||||
stream >> wd.generation;
|
||||
stream >> wd.valueEnabled;
|
||||
stream >> wd.valueEditable;
|
||||
stream >> wd.error;
|
||||
|
@@ -31,6 +31,7 @@
|
||||
**************************************************************************/
|
||||
|
||||
#include "debuggertooltipmanager.h"
|
||||
#include "debuggerinternalconstants.h"
|
||||
#include "watchutils.h"
|
||||
#include "debuggerengine.h"
|
||||
#include "debuggeractions.h"
|
||||
@@ -617,7 +618,7 @@ DebuggerToolTipWidget::DebuggerToolTipWidget(QWidget *parent) :
|
||||
m_titleLabel(new DraggableLabel),
|
||||
m_engineAcquired(false),
|
||||
m_creationDate(QDate::currentDate()),
|
||||
m_debuggerModel(TooltipsWatch),
|
||||
m_debuggerModel(TooltipType),
|
||||
m_treeView(new DebuggerToolTipTreeView),
|
||||
m_defaultModel(new QStandardItemModel(this))
|
||||
{
|
||||
@@ -664,7 +665,7 @@ bool DebuggerToolTipWidget::matches(const QString &fileName,
|
||||
return function == m_context.function;
|
||||
}
|
||||
|
||||
void DebuggerToolTipWidget::acquireEngine(Debugger::DebuggerEngine *engine)
|
||||
void DebuggerToolTipWidget::acquireEngine(DebuggerEngine *engine)
|
||||
{
|
||||
QTC_ASSERT(engine, return);
|
||||
|
||||
@@ -836,7 +837,7 @@ void DebuggerToolTipWidget::saveSessionData(QXmlStreamWriter &w) const
|
||||
}
|
||||
|
||||
/*!
|
||||
\class Debugger::Internal::DebuggerToolTipExpressionFilterModel
|
||||
\class Debugger::Internal::TooltipFilterModel
|
||||
|
||||
\brief Model for tooltips filtering a local variable using the locals or tooltip model,
|
||||
matching on the name.
|
||||
@@ -847,50 +848,46 @@ void DebuggerToolTipWidget::saveSessionData(QXmlStreamWriter &w) const
|
||||
In addition, suppress the model's tooltip data to avoid a tooltip on a tooltip.
|
||||
*/
|
||||
|
||||
class DebuggerToolTipExpressionFilterModel : public QSortFilterProxyModel
|
||||
class TooltipFilterModel : public QSortFilterProxyModel
|
||||
{
|
||||
public:
|
||||
explicit DebuggerToolTipExpressionFilterModel(QAbstractItemModel *model, const QString &exp, QObject *parent = 0);
|
||||
virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
|
||||
|
||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
|
||||
private:
|
||||
const QStringList m_expressions;
|
||||
};
|
||||
|
||||
DebuggerToolTipExpressionFilterModel::DebuggerToolTipExpressionFilterModel(QAbstractItemModel *model,
|
||||
const QString &exp,
|
||||
QObject *parent) :
|
||||
QSortFilterProxyModel(parent),
|
||||
m_expressions(exp.split(QLatin1Char('.')))
|
||||
TooltipFilterModel(QAbstractItemModel *model, const QString &exp, int debuggerModel) :
|
||||
m_expressions(exp.split(QLatin1Char('.'))),
|
||||
m_debuggerModel(debuggerModel)
|
||||
{
|
||||
setSourceModel(model);
|
||||
}
|
||||
|
||||
QVariant DebuggerToolTipExpressionFilterModel::data(const QModelIndex &index, int role) const
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const
|
||||
{
|
||||
return role != Qt::ToolTipRole ?
|
||||
QSortFilterProxyModel::data(index, role) : QVariant();
|
||||
return role == Qt::ToolTipRole
|
||||
? QVariant() : QSortFilterProxyModel::data(index, role);
|
||||
}
|
||||
|
||||
// Return depth of a model index, that is, 0 for root index, 1 for level-1 children, etc.
|
||||
static inline int indexDepth(QModelIndex index)
|
||||
{
|
||||
int depth = 0;
|
||||
for ( ; index.isValid() ; index = index.parent())
|
||||
depth++;
|
||||
return depth;
|
||||
}
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
|
||||
|
||||
bool DebuggerToolTipExpressionFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||
private:
|
||||
const QStringList m_expressions;
|
||||
int m_debuggerModel;
|
||||
};
|
||||
|
||||
bool TooltipFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||
{
|
||||
// Match on expression for top level, else pass through.
|
||||
const int depth = indexDepth(sourceParent);
|
||||
if (depth >= m_expressions.size()) // No filters at this level
|
||||
return true;
|
||||
const QModelIndex nameIndex = sourceModel()->index(sourceRow, 0, sourceParent);
|
||||
return nameIndex.data().toString() == m_expressions.at(depth);
|
||||
QByteArray iname = nameIndex.data(LocalsINameRole).toByteArray();
|
||||
if (m_debuggerModel == LocalsType && !iname.startsWith("local"))
|
||||
return false;
|
||||
if (m_debuggerModel == TooltipType && !iname.startsWith("tooltip"))
|
||||
return false;
|
||||
// Match on expression for top level, else pass through.
|
||||
const int depth = iname.count('.');
|
||||
if (depth == 0)
|
||||
return true;
|
||||
if (depth > m_expressions.size())
|
||||
return true;
|
||||
const QString name = nameIndex.data().toString();
|
||||
//const QString exp = nameIndex.data(LocalsExpressionRole).toString();
|
||||
return name == m_expressions.at(depth - 1);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -924,6 +921,7 @@ QAbstractItemModel *DebuggerToolTipTreeView::swapModel(QAbstractItemModel *newMo
|
||||
if (previousModel)
|
||||
previousModel->disconnect(SIGNAL(rowsInserted(QModelIndex,int,int)), this);
|
||||
setModel(newModel);
|
||||
//setRootIndex(newModel->index(0, 0));
|
||||
connect(newModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
|
||||
this, SLOT(computeSize()), Qt::QueuedConnection);
|
||||
computeSize();
|
||||
@@ -991,24 +989,12 @@ void DebuggerToolTipTreeView::computeSize()
|
||||
setRootIsDecorated(rootDecorated);
|
||||
}
|
||||
|
||||
void DebuggerToolTipWidget::doAcquireEngine(Debugger::DebuggerEngine *engine)
|
||||
void DebuggerToolTipWidget::doAcquireEngine(DebuggerEngine *engine)
|
||||
{
|
||||
// Create a filter model on the debugger's model and switch to it.
|
||||
QAbstractItemModel *model = 0;
|
||||
switch (m_debuggerModel) {
|
||||
case LocalsWatch:
|
||||
model = engine->localsModel();
|
||||
break;
|
||||
case WatchersWatch:
|
||||
model = engine->watchersModel();
|
||||
break;
|
||||
case TooltipsWatch:
|
||||
model = engine->toolTipsModel();
|
||||
break;
|
||||
}
|
||||
QTC_ASSERT(model, return);
|
||||
DebuggerToolTipExpressionFilterModel *filterModel =
|
||||
new DebuggerToolTipExpressionFilterModel(model, m_expression);
|
||||
QAbstractItemModel *model = engine->watchModel();
|
||||
TooltipFilterModel *filterModel =
|
||||
new TooltipFilterModel(model, m_expression, m_debuggerModel);
|
||||
swapModel(filterModel);
|
||||
}
|
||||
|
||||
@@ -1311,7 +1297,7 @@ void DebuggerToolTipManager::slotUpdateVisibleToolTips()
|
||||
}
|
||||
}
|
||||
|
||||
void DebuggerToolTipManager::slotDebuggerStateChanged(Debugger::DebuggerState state)
|
||||
void DebuggerToolTipManager::slotDebuggerStateChanged(DebuggerState state)
|
||||
{
|
||||
const QObject *engine = sender();
|
||||
QTC_ASSERT(engine, return);
|
||||
@@ -1319,7 +1305,7 @@ void DebuggerToolTipManager::slotDebuggerStateChanged(Debugger::DebuggerState st
|
||||
const QString name = engine->objectName();
|
||||
if (debugToolTips)
|
||||
qDebug() << "DebuggerToolTipWidget::debuggerStateChanged"
|
||||
<< engine << Debugger::DebuggerEngine::stateName(state);
|
||||
<< engine << DebuggerEngine::stateName(state);
|
||||
|
||||
// Release at earliest possible convenience.
|
||||
switch (state) {
|
||||
|
@@ -63,8 +63,11 @@ void AbstractPlainGdbAdapter::setupInferior()
|
||||
QString args = startParameters().processArgs;
|
||||
m_engine->postCommand("-exec-arguments " + toLocalEncoding(args));
|
||||
}
|
||||
if (m_engine->gdbVersion() > 70000)
|
||||
m_engine->postCommand("-file-exec-and-symbols \"" + execFilePath() + '"',
|
||||
CB(handleFileExecAndSymbols));
|
||||
else
|
||||
m_engine->postCommand("file " + execFilePath(), CB(handleFileExecAndSymbols));
|
||||
}
|
||||
|
||||
void AbstractPlainGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
|
||||
|
@@ -716,7 +716,7 @@ static bool parseConsoleStream(const GdbResponse &response, GdbMi *contents)
|
||||
void GdbEngine::updateLocalsClassic()
|
||||
{
|
||||
PRECONDITION;
|
||||
m_pendingWatchRequests = 0;
|
||||
//m_pendingWatchRequests = 0;
|
||||
m_pendingBreakpointRequests = 0;
|
||||
m_processedNames.clear();
|
||||
|
||||
@@ -724,15 +724,14 @@ void GdbEngine::updateLocalsClassic()
|
||||
qDebug() << "\nRESET PENDING";
|
||||
//m_toolTipCache.clear();
|
||||
clearToolTip();
|
||||
watchHandler()->beginCycle();
|
||||
|
||||
QByteArray level = QByteArray::number(currentFrame());
|
||||
// '2' is 'list with type and value'
|
||||
QByteArray cmd = "-stack-list-arguments 2 " + level + ' ' + level;
|
||||
postCommand(cmd, WatchUpdate,
|
||||
postCommand(cmd, Discardable,
|
||||
CB(handleStackListArgumentsClassic));
|
||||
// '2' is 'list with type and value'
|
||||
postCommand("-stack-list-locals 2", WatchUpdate,
|
||||
postCommand("-stack-list-locals 2", Discardable,
|
||||
CB(handleStackListLocalsClassic)); // stage 2/2
|
||||
}
|
||||
|
||||
@@ -754,9 +753,9 @@ void GdbEngine::runDirectDebuggingHelperClassic(const WatchData &data, bool dump
|
||||
|
||||
QVariant var;
|
||||
var.setValue(data);
|
||||
postCommand(cmd, WatchUpdate, CB(handleDebuggingHelperValue3Classic), var);
|
||||
postCommand(cmd, Discardable, CB(handleDebuggingHelperValue3Classic), var);
|
||||
|
||||
showStatusMessage(msgRetrievingWatchData(m_pendingWatchRequests + 1), 10000);
|
||||
showStatusMessage(msgRetrievingWatchData(m_uncompleted.size()), 10000);
|
||||
}
|
||||
|
||||
void GdbEngine::runDebuggingHelperClassic(const WatchData &data0, bool dumpChildren)
|
||||
@@ -811,25 +810,25 @@ void GdbEngine::runDebuggingHelperClassic(const WatchData &data0, bool dumpChild
|
||||
cmd += ',' + ex;
|
||||
cmd += ')';
|
||||
|
||||
postCommand(cmd, WatchUpdate | NonCriticalResponse);
|
||||
postCommand(cmd, Discardable | NonCriticalResponse);
|
||||
|
||||
showStatusMessage(msgRetrievingWatchData(m_pendingWatchRequests + 1), 10000);
|
||||
showStatusMessage(msgRetrievingWatchData(m_uncompleted.size()), 10000);
|
||||
|
||||
// retrieve response
|
||||
postCommand("p (char*)&qDumpOutBuffer", WatchUpdate,
|
||||
postCommand("p (char*)&qDumpOutBuffer", Discardable,
|
||||
CB(handleDebuggingHelperValue2Classic), qVariantFromValue(data));
|
||||
}
|
||||
|
||||
void GdbEngine::createGdbVariableClassic(const WatchData &data)
|
||||
{
|
||||
PRECONDITION;
|
||||
postCommand("-var-delete \"" + data.iname + '"', WatchUpdate);
|
||||
postCommand("-var-delete \"" + data.iname + '"', Discardable);
|
||||
QByteArray exp = data.exp;
|
||||
if (exp.isEmpty() && data.address)
|
||||
exp = "*(" + gdbQuoteTypes(data.type) + "*)" + data.hexAddress();
|
||||
QVariant val = QVariant::fromValue<WatchData>(data);
|
||||
postCommand("-var-create \"" + data.iname + "\" * \"" + exp + '"',
|
||||
WatchUpdate, CB(handleVarCreate), val);
|
||||
Discardable, CB(handleVarCreate), val);
|
||||
}
|
||||
|
||||
void GdbEngine::updateSubItemClassic(const WatchData &data0)
|
||||
@@ -929,7 +928,7 @@ void GdbEngine::updateSubItemClassic(const WatchData &data0)
|
||||
if (debugSubItem)
|
||||
qDebug() << "UPDATE SUBITEM: VALUE";
|
||||
QByteArray cmd = "-var-evaluate-expression \"" + data.iname + '"';
|
||||
postCommand(cmd, WatchUpdate,
|
||||
postCommand(cmd, Discardable,
|
||||
CB(handleEvaluateExpressionClassic), QVariant::fromValue(data));
|
||||
return;
|
||||
}
|
||||
@@ -953,7 +952,7 @@ void GdbEngine::updateSubItemClassic(const WatchData &data0)
|
||||
if (data.isChildrenNeeded()) {
|
||||
QTC_ASSERT(!data.variable.isEmpty(), return); // tested above
|
||||
QByteArray cmd = "-var-list-children --all-values \"" + data.variable + '"';
|
||||
postCommand(cmd, WatchUpdate,
|
||||
postCommand(cmd, Discardable,
|
||||
CB(handleVarListChildrenClassic), QVariant::fromValue(data));
|
||||
return;
|
||||
}
|
||||
@@ -999,7 +998,7 @@ void GdbEngine::handleDebuggingHelperValue2Classic(const GdbResponse &response)
|
||||
if (m_cookieForToken.contains(response.token - 1)) {
|
||||
m_cookieForToken.remove(response.token - 1);
|
||||
showMessage(_("DETECTING LOST COMMAND %1").arg(response.token - 1));
|
||||
--m_pendingWatchRequests;
|
||||
// --m_pendingWatchRequests;
|
||||
data.setError(WatchData::msgNotInScope());
|
||||
insertData(data);
|
||||
return;
|
||||
@@ -1025,7 +1024,7 @@ void GdbEngine::handleDebuggingHelperValue2Classic(const GdbResponse &response)
|
||||
parseWatchData(watchHandler()->expandedINames(), data, contents, &list);
|
||||
//for (int i = 0; i != list.size(); ++i)
|
||||
// qDebug() << "READ: " << list.at(i).toString();
|
||||
watchHandler()->insertBulkData(list);
|
||||
watchHandler()->insertData(list);
|
||||
}
|
||||
|
||||
void GdbEngine::handleDebuggingHelperValue3Classic(const GdbResponse &response)
|
||||
@@ -1082,7 +1081,7 @@ void GdbEngine::handleDebuggingHelperValue3Classic(const GdbResponse &response)
|
||||
QByteArray cmd = "qdumpqstring (" + data1.exp + ')';
|
||||
QVariant var;
|
||||
var.setValue(data1);
|
||||
postCommand(cmd, WatchUpdate,
|
||||
postCommand(cmd, Discardable,
|
||||
CB(handleDebuggingHelperValue3Classic), var);
|
||||
}
|
||||
}
|
||||
@@ -1101,6 +1100,9 @@ void GdbEngine::handleDebuggingHelperValue3Classic(const GdbResponse &response)
|
||||
|
||||
void GdbEngine::tryLoadDebuggingHelpersClassic()
|
||||
{
|
||||
if (m_forceAsyncModel)
|
||||
return;
|
||||
|
||||
PRECONDITION;
|
||||
if (m_gdbAdapter->dumperHandling() == AbstractGdbAdapter::DumperNotAvailable) {
|
||||
// Load at least gdb macro based dumpers.
|
||||
@@ -1171,12 +1173,12 @@ void GdbEngine::updateAllClassic()
|
||||
qDebug() << state());
|
||||
tryLoadDebuggingHelpersClassic();
|
||||
reloadModulesInternal();
|
||||
postCommand("-stack-list-frames", WatchUpdate,
|
||||
postCommand("-stack-list-frames", Discardable,
|
||||
CB(handleStackListFrames),
|
||||
QVariant::fromValue<StackCookie>(StackCookie(false, true)));
|
||||
stackHandler()->setCurrentIndex(0);
|
||||
if (supportsThreads())
|
||||
postCommand("-thread-list-ids", WatchUpdate, CB(handleThreadListIds), 0);
|
||||
postCommand("-thread-list-ids", Discardable, CB(handleThreadListIds), 0);
|
||||
reloadRegisters();
|
||||
updateLocals();
|
||||
}
|
||||
@@ -1248,11 +1250,10 @@ void GdbEngine::handleStackListLocalsClassic(const GdbResponse &response)
|
||||
frame.function, frame.file, frame.line,
|
||||
&uninitializedVariables);
|
||||
}
|
||||
QList<WatchData> list;
|
||||
foreach (const GdbMi &item, locals) {
|
||||
const WatchData data = localVariable(item, uninitializedVariables, &seen);
|
||||
if (data.isValid())
|
||||
list.push_back(data);
|
||||
insertData(data);
|
||||
}
|
||||
|
||||
if (!m_resultVarName.isEmpty()) {
|
||||
@@ -1260,10 +1261,9 @@ void GdbEngine::handleStackListLocalsClassic(const GdbResponse &response)
|
||||
rd.iname = "return.0";
|
||||
rd.name = QLatin1String("return");
|
||||
rd.exp = m_resultVarName;
|
||||
list.append(rd);
|
||||
insertData(rd);
|
||||
}
|
||||
|
||||
watchHandler()->insertBulkData(list);
|
||||
watchHandler()->updateWatchers();
|
||||
}
|
||||
|
||||
@@ -1371,7 +1371,7 @@ void GdbEngine::handleVarListChildrenHelperClassic(const GdbMi &item,
|
||||
data.setChildrenUnneeded();
|
||||
QByteArray cmd = "-var-list-children --all-values \"" + data.variable + '"';
|
||||
//iname += '.' + exp;
|
||||
postCommand(cmd, WatchUpdate,
|
||||
postCommand(cmd, Discardable,
|
||||
CB(handleVarListChildrenClassic), QVariant::fromValue(data));
|
||||
} else if (!startsWithDigit(QLatin1String(exp))
|
||||
&& item.findChild("numchild").data() == "0") {
|
||||
@@ -1390,7 +1390,7 @@ void GdbEngine::handleVarListChildrenHelperClassic(const GdbMi &item,
|
||||
WatchData data;
|
||||
data.iname = name;
|
||||
QByteArray cmd = "-var-list-children --all-values \"" + data.variable + '"';
|
||||
postCommand(cmd, WatchUpdate,
|
||||
postCommand(cmd, Discardable,
|
||||
CB(handleVarListChildrenClassic), QVariant::fromValue(data));
|
||||
} else if (exp == "staticMetaObject") {
|
||||
// && item.findChild("type").data() == "const QMetaObject")
|
||||
@@ -1464,9 +1464,6 @@ void GdbEngine::handleVarListChildrenClassic(const GdbResponse &response)
|
||||
//qDebug() << "VAR_LIST_CHILDREN: PARENT" << data.toString();
|
||||
QList<GdbMi> children = response.data.findChild("children").children();
|
||||
|
||||
for (int i = 0; i != children.size(); ++i)
|
||||
handleVarListChildrenHelperClassic(children.at(i), data, i);
|
||||
|
||||
if (children.isEmpty()) {
|
||||
// happens e.g. if no debug information is present or
|
||||
// if the class really has no children
|
||||
@@ -1479,7 +1476,8 @@ void GdbEngine::handleVarListChildrenClassic(const GdbResponse &response)
|
||||
insertData(data1);
|
||||
data.setAllUnneeded();
|
||||
insertData(data);
|
||||
} else if (data.variable.endsWith("private")
|
||||
} else {
|
||||
if (data.variable.endsWith("private")
|
||||
|| data.variable.endsWith("protected")
|
||||
|| data.variable.endsWith("public")) {
|
||||
// this skips the spurious "public", "private" etc levels
|
||||
@@ -1488,6 +1486,9 @@ void GdbEngine::handleVarListChildrenClassic(const GdbResponse &response)
|
||||
data.setChildrenUnneeded();
|
||||
insertData(data);
|
||||
}
|
||||
for (int i = 0; i != children.size(); ++i)
|
||||
handleVarListChildrenHelperClassic(children.at(i), data, i);
|
||||
}
|
||||
} else {
|
||||
data.setError(QString::fromLocal8Bit(response.data.findChild("msg").data()));
|
||||
}
|
||||
|
@@ -255,7 +255,6 @@ GdbEngine::GdbEngine(const DebuggerStartParameters &startParameters,
|
||||
m_oldestAcceptableToken = -1;
|
||||
m_nonDiscardableCount = 0;
|
||||
m_outputCodec = QTextCodec::codecForLocale();
|
||||
m_pendingWatchRequests = 0;
|
||||
m_pendingBreakpointRequests = 0;
|
||||
m_commandsDoneCallback = 0;
|
||||
m_stackNeeded = false;
|
||||
@@ -263,6 +262,7 @@ GdbEngine::GdbEngine(const DebuggerStartParameters &startParameters,
|
||||
m_disassembleUsesComma = false;
|
||||
m_actingOnExpectedStop = false;
|
||||
m_fullStartDone = false;
|
||||
m_forceAsyncModel = false;
|
||||
|
||||
invalidateSourcesList();
|
||||
|
||||
@@ -788,7 +788,8 @@ void GdbEngine::readGdbStandardOutput()
|
||||
int newstart = 0;
|
||||
int scan = m_inbuffer.size();
|
||||
|
||||
m_inbuffer.append(gdbProc()->readAllStandardOutput());
|
||||
QByteArray out = gdbProc()->readAllStandardOutput();
|
||||
m_inbuffer.append(out);
|
||||
|
||||
// This can trigger when a dialog starts a nested event loop.
|
||||
if (m_busy)
|
||||
@@ -811,7 +812,8 @@ void GdbEngine::readGdbStandardOutput()
|
||||
continue;
|
||||
}
|
||||
m_busy = true;
|
||||
handleResponse(QByteArray::fromRawData(m_inbuffer.constData() + start, end - start));
|
||||
QByteArray ba = QByteArray::fromRawData(m_inbuffer.constData() + start, end - start);
|
||||
handleResponse(ba);
|
||||
m_busy = false;
|
||||
}
|
||||
m_inbuffer.clear();
|
||||
@@ -903,17 +905,13 @@ void GdbEngine::postCommandHelper(const GdbCommand &cmd)
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmd.flags & RebuildWatchModel) {
|
||||
++m_pendingWatchRequests;
|
||||
PENDING_DEBUG(" WATCH MODEL:" << cmd.command << "=>" << cmd.callbackName
|
||||
<< "INCREMENTS PENDING TO" << m_pendingWatchRequests);
|
||||
} else if (cmd.flags & RebuildBreakpointModel) {
|
||||
if (cmd.flags & RebuildBreakpointModel) {
|
||||
++m_pendingBreakpointRequests;
|
||||
PENDING_DEBUG(" BRWAKPOINT MODEL:" << cmd.command << "=>" << cmd.callbackName
|
||||
<< "INCREMENTS PENDING TO" << m_pendingBreakpointRequests);
|
||||
} else {
|
||||
PENDING_DEBUG(" OTHER (IN):" << cmd.command << "=>" << cmd.callbackName
|
||||
<< "LEAVES PENDING WATCH AT" << m_pendingWatchRequests
|
||||
<< "LEAVES PENDING WATCH AT" << m_uncompleted.size()
|
||||
<< "LEAVES PENDING BREAKPOINT AT" << m_pendingBreakpointRequests);
|
||||
}
|
||||
|
||||
@@ -1055,7 +1053,6 @@ void GdbEngine::commandTimeout()
|
||||
if (mb->exec() == QMessageBox::Ok) {
|
||||
showMessage(_("KILLING DEBUGGER AS REQUESTED BY USER"));
|
||||
// This is an undefined state, so we just pull the emergency brake.
|
||||
watchHandler()->endCycle();
|
||||
gdbProc()->kill();
|
||||
} else {
|
||||
showMessage(_("CONTINUE DEBUGGER AS REQUESTED BY USER"));
|
||||
@@ -1205,25 +1202,17 @@ void GdbEngine::handleResultRecord(GdbResponse *response)
|
||||
else if (cmd.adapterCallback)
|
||||
(m_gdbAdapter->*cmd.adapterCallback)(*response);
|
||||
|
||||
if (cmd.flags & RebuildWatchModel) {
|
||||
--m_pendingWatchRequests;
|
||||
PENDING_DEBUG(" WATCH" << cmd.command << "=>" << cmd.callbackName
|
||||
<< "DECREMENTS PENDING WATCH TO" << m_pendingWatchRequests);
|
||||
if (m_pendingWatchRequests <= 0) {
|
||||
PENDING_DEBUG("\n\n ... AND TRIGGERS WATCH MODEL UPDATE\n");
|
||||
rebuildWatchModel();
|
||||
}
|
||||
} else if (cmd.flags & RebuildBreakpointModel) {
|
||||
if (cmd.flags & RebuildBreakpointModel) {
|
||||
--m_pendingBreakpointRequests;
|
||||
PENDING_DEBUG(" BREAKPOINT" << cmd.command << "=>" << cmd.callbackName
|
||||
<< "DECREMENTS PENDING TO" << m_pendingWatchRequests);
|
||||
<< "DECREMENTS PENDING TO" << m_uncompleted.size());
|
||||
if (m_pendingBreakpointRequests <= 0) {
|
||||
PENDING_DEBUG("\n\n ... AND TRIGGERS BREAKPOINT MODEL UPDATE\n");
|
||||
attemptBreakpointSynchronization();
|
||||
}
|
||||
} else {
|
||||
PENDING_DEBUG(" OTHER (OUT):" << cmd.command << "=>" << cmd.callbackName
|
||||
<< "LEAVES PENDING WATCH AT" << m_pendingWatchRequests
|
||||
<< "LEAVES PENDING WATCH AT" << m_uncompleted.size()
|
||||
<< "LEAVES PENDING BREAKPOINT AT" << m_pendingBreakpointRequests);
|
||||
}
|
||||
|
||||
@@ -3918,10 +3907,10 @@ bool GdbEngine::supportsThreads() const
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool GdbEngine::showToolTip()
|
||||
void GdbEngine::showToolTip()
|
||||
{
|
||||
if (m_toolTipContext.isNull())
|
||||
return false;
|
||||
return;
|
||||
const QString expression = m_toolTipContext->expression;
|
||||
const QByteArray iname = tooltipIName(m_toolTipContext->expression);
|
||||
if (DebuggerToolTipManager::debug())
|
||||
@@ -3929,15 +3918,15 @@ bool GdbEngine::showToolTip()
|
||||
|
||||
if (!debuggerCore()->boolSetting(UseToolTipsInMainEditor)) {
|
||||
watchHandler()->removeData(iname);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!watchHandler()->isValidToolTip(iname)) {
|
||||
watchHandler()->removeData(iname);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
DebuggerToolTipWidget *tw = new DebuggerToolTipWidget;
|
||||
tw->setDebuggerModel(TooltipsWatch);
|
||||
tw->setDebuggerModel(TooltipType);
|
||||
tw->setExpression(expression);
|
||||
tw->setContext(*m_toolTipContext);
|
||||
tw->acquireEngine(this);
|
||||
@@ -3945,7 +3934,6 @@ bool GdbEngine::showToolTip()
|
||||
m_toolTipContext->editor, tw);
|
||||
// Prevent tooltip from re-occurring (classic GDB, QTCREATORBUG-4711).
|
||||
m_toolTipContext.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
QString GdbEngine::tooltipExpression() const
|
||||
@@ -4034,7 +4022,6 @@ bool GdbEngine::setToolTipExpression(const QPoint &mousePos,
|
||||
toolTip.exp = exp.toLatin1();
|
||||
toolTip.name = exp;
|
||||
toolTip.iname = tooltipIName(exp);
|
||||
watchHandler()->removeData(toolTip.iname);
|
||||
watchHandler()->insertData(toolTip);
|
||||
}
|
||||
return true;
|
||||
@@ -4071,19 +4058,12 @@ bool GdbEngine::hasDebuggingHelperForType(const QByteArray &type) const
|
||||
return m_dumperHelper.type(type) != DumperHelper::UnknownType;
|
||||
}
|
||||
|
||||
|
||||
void GdbEngine::updateWatchData(const WatchData &data, const WatchUpdateFlags &flags)
|
||||
{
|
||||
if (isSynchronous()) {
|
||||
// This should only be called for fresh expanded items, not for
|
||||
// items that had their children retrieved earlier.
|
||||
//qDebug() << "\nUPDATE WATCH DATA: " << data.toString() << "\n";
|
||||
#if 0
|
||||
WatchData data1 = data;
|
||||
data1.setAllUnneeded();
|
||||
insertData(data1);
|
||||
rebuildModel();
|
||||
#else
|
||||
if (data.iname.endsWith("."))
|
||||
return;
|
||||
|
||||
@@ -4106,53 +4086,26 @@ void GdbEngine::updateWatchData(const WatchData &data, const WatchUpdateFlags &f
|
||||
// triggered e.g. by manually entered command in the gdb console?
|
||||
//qDebug() << "TRY PARTIAL: " << flags.tryIncremental
|
||||
// << hasPython()
|
||||
// << (m_pendingWatchRequests == 0)
|
||||
// << (m_pendingBreakpointRequests == 0);
|
||||
|
||||
UpdateParameters params;
|
||||
params.tooltipOnly = data.iname.startsWith("tooltip");
|
||||
params.tryPartial = flags.tryIncremental
|
||||
&& hasPython()
|
||||
&& m_pendingWatchRequests == 0
|
||||
&& m_pendingBreakpointRequests == 0;
|
||||
params.varList = data.iname;
|
||||
|
||||
updateLocalsPython(params);
|
||||
#endif
|
||||
} else {
|
||||
// Bump requests to avoid model rebuilding during the nested
|
||||
// updateWatchModel runs.
|
||||
++m_pendingWatchRequests;
|
||||
PENDING_DEBUG("UPDATE WATCH BUMPS PENDING UP TO " << m_pendingWatchRequests);
|
||||
#if 1
|
||||
QMetaObject::invokeMethod(this, "updateWatchDataHelper",
|
||||
Qt::QueuedConnection, Q_ARG(WatchData, data));
|
||||
#else
|
||||
updateWatchDataHelper(data);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void GdbEngine::updateWatchDataHelper(const WatchData &data)
|
||||
{
|
||||
//m_pendingRequests = 0;
|
||||
PENDING_DEBUG("UPDATE WATCH DATA");
|
||||
# if DEBUG_PENDING
|
||||
//qDebug() << "##############################################";
|
||||
qDebug() << "UPDATE MODEL, FOUND INCOMPLETE:";
|
||||
//qDebug() << data.toString();
|
||||
# endif
|
||||
|
||||
PENDING_DEBUG("UPDATE WATCH BUMPS PENDING UP TO " << m_uncompleted.size());
|
||||
updateSubItemClassic(data);
|
||||
//PENDING_DEBUG("INTERNAL TRIGGERING UPDATE WATCH MODEL");
|
||||
--m_pendingWatchRequests;
|
||||
PENDING_DEBUG("UPDATE WATCH DONE BUMPS PENDING DOWN TO " << m_pendingWatchRequests);
|
||||
if (m_pendingWatchRequests <= 0)
|
||||
rebuildWatchModel();
|
||||
}
|
||||
}
|
||||
|
||||
void GdbEngine::rebuildWatchModel()
|
||||
{
|
||||
QTC_CHECK(m_completed.isEmpty());
|
||||
QTC_CHECK(m_uncompleted.isEmpty());
|
||||
static int count = 0;
|
||||
++count;
|
||||
if (!isSynchronous())
|
||||
@@ -4162,7 +4115,6 @@ void GdbEngine::rebuildWatchModel()
|
||||
showMessage(LogWindow::logTimeStamp(), LogMiscInput);
|
||||
showMessage(_("<Rebuild Watchmodel %1>").arg(count), LogMiscInput);
|
||||
showStatusMessage(tr("Finished retrieving data"), 400);
|
||||
watchHandler()->endCycle();
|
||||
showToolTip();
|
||||
handleAutoTests();
|
||||
}
|
||||
@@ -4332,15 +4284,23 @@ WatchData GdbEngine::localVariable(const GdbMi &item,
|
||||
return data;
|
||||
}
|
||||
|
||||
void GdbEngine::insertData(const WatchData &data0)
|
||||
void GdbEngine::insertData(const WatchData &data)
|
||||
{
|
||||
PENDING_DEBUG("INSERT DATA" << data0.toString());
|
||||
WatchData data = data0;
|
||||
if (data.value.startsWith(QLatin1String("mi_cmd_var_create:"))) {
|
||||
qDebug() << "BOGUS VALUE:" << data.toString();
|
||||
return;
|
||||
PENDING_DEBUG("INSERT DATA" << data.toString());
|
||||
if (data.isSomethingNeeded()) {
|
||||
m_uncompleted.insert(data.iname);
|
||||
WatchUpdateFlags flags;
|
||||
flags.tryIncremental = true;
|
||||
updateWatchData(data, flags);
|
||||
} else {
|
||||
m_completed.append(data);
|
||||
m_uncompleted.remove(data.iname);
|
||||
if (m_uncompleted.isEmpty()) {
|
||||
watchHandler()->insertData(m_completed);
|
||||
m_completed.clear();
|
||||
rebuildWatchModel();
|
||||
}
|
||||
}
|
||||
watchHandler()->insertData(data);
|
||||
}
|
||||
|
||||
void GdbEngine::assignValueInDebugger(const WatchData *data,
|
||||
@@ -4901,12 +4861,6 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &settingsIdHint)
|
||||
|
||||
postCommand("disassemble 0 0", ConsoleCommand, CB(handleDisassemblerCheck));
|
||||
|
||||
if (sp.breakOnMain) {
|
||||
QByteArray cmd = "tbreak ";
|
||||
cmd += sp.toolChainAbi.os() == Abi::WindowsOS ? "qMain" : "main";
|
||||
postCommand(cmd);
|
||||
}
|
||||
|
||||
if (attemptQuickStart()) {
|
||||
postCommand("set auto-solib-add off", ConsoleCommand);
|
||||
} else {
|
||||
@@ -4941,6 +4895,9 @@ void GdbEngine::loadInitScript()
|
||||
|
||||
void GdbEngine::loadPythonDumpers()
|
||||
{
|
||||
if (m_forceAsyncModel)
|
||||
return;
|
||||
|
||||
const QByteArray dumperSourcePath =
|
||||
Core::ICore::resourcePath().toLocal8Bit() + "/dumper/";
|
||||
|
||||
@@ -5091,6 +5048,12 @@ void GdbEngine::handleInferiorPrepared()
|
||||
|
||||
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||
|
||||
if (sp.breakOnMain) {
|
||||
QByteArray cmd = "tbreak ";
|
||||
cmd += sp.toolChainAbi.os() == Abi::WindowsOS ? "qMain" : "main";
|
||||
postCommand(cmd);
|
||||
}
|
||||
|
||||
// Initial attempt to set breakpoints.
|
||||
if (sp.startMode != AttachCore) {
|
||||
showStatusMessage(tr("Setting breakpoints..."));
|
||||
@@ -5361,6 +5324,9 @@ void GdbEngine::requestDebugInformation(const DebugInfoTask &task)
|
||||
|
||||
bool GdbEngine::attemptQuickStart() const
|
||||
{
|
||||
if (m_forceAsyncModel)
|
||||
return false;
|
||||
|
||||
// Don't try if the user does not ask for it.
|
||||
if (!debuggerCore()->boolSetting(AttemptQuickStart))
|
||||
return false;
|
||||
|
@@ -36,6 +36,7 @@
|
||||
#include "debuggerengine.h"
|
||||
|
||||
#include "stackframe.h"
|
||||
#include "watchhandler.h"
|
||||
#include "watchutils.h"
|
||||
|
||||
#include <QByteArray>
|
||||
@@ -80,16 +81,6 @@ enum DebuggingHelperState
|
||||
DebuggingHelperUnavailable
|
||||
};
|
||||
|
||||
class UpdateParameters
|
||||
{
|
||||
public:
|
||||
UpdateParameters() { tryPartial = tooltipOnly = false; }
|
||||
|
||||
bool tryPartial;
|
||||
bool tooltipOnly;
|
||||
QByteArray varList;
|
||||
};
|
||||
|
||||
/* This is only used with Mac gdb since 2.2
|
||||
*
|
||||
* "Custom dumper" is a library compiled against the current
|
||||
@@ -322,9 +313,6 @@ private: ////////// Gdb Command Management //////////
|
||||
NeedsStop = 1,
|
||||
// No need to wait for the reply before continuing inferior.
|
||||
Discardable = 2,
|
||||
// Trigger watch model rebuild when no such commands are pending anymore.
|
||||
RebuildWatchModel = 4,
|
||||
WatchUpdate = Discardable | RebuildWatchModel,
|
||||
// We can live without receiving an answer.
|
||||
NonCriticalResponse = 8,
|
||||
// Callback expects GdbResultRunning instead of GdbResultDone.
|
||||
@@ -407,7 +395,6 @@ private: ////////// Gdb Command Management //////////
|
||||
int m_oldestAcceptableToken;
|
||||
int m_nonDiscardableCount;
|
||||
|
||||
int m_pendingWatchRequests; // Watch updating commands in flight
|
||||
int m_pendingBreakpointRequests; // Watch updating commands in flight
|
||||
|
||||
typedef void (GdbEngine::*CommandsDoneCallback)();
|
||||
@@ -630,13 +617,11 @@ private: ////////// View & Data Stuff //////////
|
||||
virtual void watchPoint(const QPoint &);
|
||||
void handleWatchPoint(const GdbResponse &response);
|
||||
|
||||
// FIXME: BaseClass. called to improve situation for a watch item
|
||||
void updateSubItemClassic(const WatchData &data);
|
||||
|
||||
void virtual updateWatchData(const WatchData &data, const WatchUpdateFlags &flags);
|
||||
Q_SLOT void updateWatchDataHelper(const WatchData &data);
|
||||
void updateWatchData(const WatchData &data, const WatchUpdateFlags &flags);
|
||||
void rebuildWatchModel();
|
||||
bool showToolTip();
|
||||
void showToolTip();
|
||||
|
||||
void insertData(const WatchData &data);
|
||||
void sendWatchParameters(const QByteArray ¶ms0);
|
||||
@@ -753,6 +738,11 @@ private: ////////// View & Data Stuff //////////
|
||||
// debug information.
|
||||
bool attemptQuickStart() const;
|
||||
bool m_fullStartDone;
|
||||
|
||||
// Test
|
||||
bool m_forceAsyncModel;
|
||||
QList<WatchData> m_completed;
|
||||
QSet<QByteArray> m_uncompleted;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -54,12 +54,11 @@ namespace Internal {
|
||||
void GdbEngine::updateLocalsPython(const UpdateParameters ¶ms)
|
||||
{
|
||||
PRECONDITION;
|
||||
m_pendingWatchRequests = 0;
|
||||
//m_pendingWatchRequests = 0;
|
||||
m_pendingBreakpointRequests = 0;
|
||||
m_processedNames.clear();
|
||||
WatchHandler *handler = watchHandler();
|
||||
handler->beginCycle(!params.tryPartial);
|
||||
|
||||
WatchHandler *handler = watchHandler();
|
||||
QByteArray expanded = "expanded:" + handler->expansionRequests() + ' ';
|
||||
expanded += "typeformats:" + handler->typeFormatRequests() + ' ';
|
||||
expanded += "formats:" + handler->individualFormatRequests();
|
||||
@@ -117,7 +116,7 @@ void GdbEngine::updateLocalsPython(const UpdateParameters ¶ms)
|
||||
|
||||
postCommand("bb options:" + options + " vars:" + params.varList + ' '
|
||||
+ resultVar + expanded + " watchers:" + watchers.toHex(),
|
||||
WatchUpdate, CB(handleStackFramePython), QVariant(params.tryPartial));
|
||||
Discardable, CB(handleStackFramePython), QVariant(params.tryPartial));
|
||||
}
|
||||
|
||||
void GdbEngine::handleStackFramePython(const GdbResponse &response)
|
||||
@@ -136,9 +135,11 @@ void GdbEngine::handleStackFramePython(const GdbResponse &response)
|
||||
}
|
||||
GdbMi all;
|
||||
all.fromStringMultiple(out);
|
||||
|
||||
GdbMi data = all.findChild("data");
|
||||
|
||||
WatchHandler *handler = watchHandler();
|
||||
QList<WatchData> list;
|
||||
|
||||
foreach (const GdbMi &child, data.children()) {
|
||||
WatchData dummy;
|
||||
dummy.iname = child.findChild("iname").data();
|
||||
@@ -151,7 +152,7 @@ void GdbEngine::handleStackFramePython(const GdbResponse &response)
|
||||
} else {
|
||||
dummy.name = _(child.findChild("name").data());
|
||||
}
|
||||
parseWatchData(watchHandler()->expandedINames(), dummy, child, &list);
|
||||
parseWatchData(handler->expandedINames(), dummy, child, &list);
|
||||
}
|
||||
const GdbMi typeInfo = all.findChild("typeinfo");
|
||||
if (typeInfo.type() == GdbMi::List) {
|
||||
@@ -169,15 +170,20 @@ void GdbEngine::handleStackFramePython(const GdbResponse &response)
|
||||
list[i].size = ti.size;
|
||||
}
|
||||
|
||||
watchHandler()->insertBulkData(list);
|
||||
if (!partial) {
|
||||
handler->removeChildren("local");
|
||||
handler->removeChildren("watch");
|
||||
}
|
||||
|
||||
handler->insertData(list);
|
||||
|
||||
//PENDING_DEBUG("AFTER handleStackFrame()");
|
||||
// FIXME: This should only be used when updateLocals() was
|
||||
// triggered by expanding an item in the view.
|
||||
if (m_pendingWatchRequests <= 0) {
|
||||
//if (m_pendingWatchRequests <= 0) {
|
||||
//PENDING_DEBUG("\n\n .... AND TRIGGERS MODEL UPDATE\n");
|
||||
rebuildWatchModel();
|
||||
}
|
||||
//}
|
||||
if (!partial)
|
||||
emit stackFrameCompleted();
|
||||
} else {
|
||||
|
@@ -496,9 +496,7 @@ void IPCEngineHost::rpcCallback(quint64 f, QByteArray payload)
|
||||
WatchHandler *wh = watchHandler();
|
||||
if (!wh)
|
||||
break;
|
||||
wh->beginCycle(fullCycle);
|
||||
wh->insertBulkData(wd);
|
||||
wh->endCycle();
|
||||
wh->insertData(wd);
|
||||
}
|
||||
break;
|
||||
case IPCEngineGuest::NotifyAddBreakpointOk:
|
||||
|
@@ -720,14 +720,12 @@ void PdbEngine::updateAll()
|
||||
|
||||
void PdbEngine::updateLocals()
|
||||
{
|
||||
WatchHandler *handler = watchHandler();
|
||||
handler->beginCycle(true);
|
||||
|
||||
QByteArray watchers;
|
||||
//if (!m_toolTipExpression.isEmpty())
|
||||
// watchers += m_toolTipExpression.toLatin1()
|
||||
// + '#' + tooltipINameForExpression(m_toolTipExpression.toLatin1());
|
||||
|
||||
WatchHandler *handler = watchHandler();
|
||||
QHash<QByteArray, int> watcherNames = handler->watcherNames();
|
||||
QHashIterator<QByteArray, int> it(watcherNames);
|
||||
while (it.hasNext()) {
|
||||
@@ -831,8 +829,7 @@ void PdbEngine::handleListLocals(const PdbResponse &response)
|
||||
//qDebug() << "CHILD: " << child.toString();
|
||||
parseWatchData(handler->expandedINames(), dummy, child, &list);
|
||||
}
|
||||
handler->insertBulkData(list);
|
||||
handler->endCycle();
|
||||
handler->insertData(list);
|
||||
}
|
||||
|
||||
bool PdbEngine::hasCapability(unsigned cap) const
|
||||
|
@@ -1000,7 +1000,6 @@ void QmlEngine::updateWatchData(const WatchData &data,
|
||||
const WatchUpdateFlags &)
|
||||
{
|
||||
// qDebug() << "UPDATE WATCH DATA" << data.toString();
|
||||
//watchHandler()->rebuildModel();
|
||||
//showStatusMessage(tr("Stopped."), 5000);
|
||||
|
||||
if (data.isInspect()) {
|
||||
@@ -1020,7 +1019,7 @@ void QmlEngine::updateWatchData(const WatchData &data,
|
||||
|
||||
|
||||
if (!data.isSomethingNeeded())
|
||||
watchHandler()->insertData(data);
|
||||
watchHandler()->insertIncompleteData(data);
|
||||
}
|
||||
|
||||
void QmlEngine::synchronizeWatchers()
|
||||
|
@@ -103,15 +103,11 @@ void QmlInspectorAgent::updateWatchData(const WatchData &data)
|
||||
if (debug)
|
||||
qDebug() << __FUNCTION__ << "(" << data.id << ")";
|
||||
|
||||
if (data.id) {
|
||||
if (data.id && !m_fetchDataIds.contains(data.id)) {
|
||||
// objects
|
||||
m_fetchDataIds << data.id;
|
||||
ObjectReference ref(data.id);
|
||||
m_fetchCurrentObjectsQueryIds << fetchContextObject(ref);
|
||||
WatchData d = data;
|
||||
d.setAllUnneeded();
|
||||
m_engine->watchHandler()->beginCycle(InspectWatch, false);
|
||||
m_engine->watchHandler()->insertData(d);
|
||||
m_engine->watchHandler()->endCycle(InspectWatch);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,12 +122,9 @@ void QmlInspectorAgent::selectObjectInTree(int debugId)
|
||||
if (m_debugIdToIname.contains(debugId)) {
|
||||
QByteArray iname = m_debugIdToIname.value(debugId);
|
||||
QTC_ASSERT(iname.startsWith("inspect."), qDebug() << iname);
|
||||
QModelIndex itemIndex = m_engine->watchHandler()->itemIndex(iname);
|
||||
QTC_ASSERT(itemIndex.isValid(),
|
||||
qDebug() << "No for " << debugId << ", iname " << iname; return;);
|
||||
if (debug)
|
||||
qDebug() << " selecting" << iname << "in tree";
|
||||
m_engine->watchHandler()->setCurrentModelIndex(InspectWatch, itemIndex);
|
||||
m_engine->watchHandler()->setCurrentItem(iname);
|
||||
m_objectToSelect = 0;
|
||||
} else {
|
||||
// we've to fetch it
|
||||
@@ -370,9 +363,8 @@ void QmlInspectorAgent::updateStatus()
|
||||
&& debuggerCore()->boolSetting(ShowQmlObjectTree)) {
|
||||
reloadEngines();
|
||||
} else {
|
||||
// clear view
|
||||
m_engine->watchHandler()->beginCycle(InspectWatch, true);
|
||||
m_engine->watchHandler()->endCycle(InspectWatch);
|
||||
// Clear view.
|
||||
m_engine->watchHandler()->removeChildren("inspect");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -588,10 +580,7 @@ void QmlInspectorAgent::objectTreeFetched(const ObjectReference &object)
|
||||
<< "entries into watch handler ...";
|
||||
}
|
||||
|
||||
WatchHandler *watchHandler = m_engine->watchHandler();
|
||||
watchHandler->beginCycle(InspectWatch, true);
|
||||
watchHandler->insertBulkData(watchData);
|
||||
watchHandler->endCycle(InspectWatch);
|
||||
m_engine->watchHandler()->insertData(watchData);
|
||||
|
||||
if (debug)
|
||||
qDebug() << "inserting entries took" << t.elapsed() << "ms";
|
||||
@@ -615,15 +604,16 @@ void QmlInspectorAgent::onCurrentObjectsFetched(const ObjectReference &obj)
|
||||
|
||||
ObjectReference last = m_fetchCurrentObjects.last();
|
||||
m_fetchCurrentObjects.clear();
|
||||
m_fetchDataIds.clear();
|
||||
|
||||
if (m_objectToSelect == last.debugId()) {
|
||||
// select item in view
|
||||
QByteArray iname = m_debugIdToIname.value(last.debugId());
|
||||
QModelIndex itemIndex = m_engine->watchHandler()->itemIndex(iname);
|
||||
QTC_ASSERT(itemIndex.isValid(), return);
|
||||
WatchHandler *handler = m_engine->watchHandler();
|
||||
QTC_ASSERT(handler->hasItem(iname), return);
|
||||
if (debug)
|
||||
qDebug() << " selecting" << iname << "in tree";
|
||||
m_engine->watchHandler()->setCurrentModelIndex(InspectWatch, itemIndex);
|
||||
handler->setCurrentItem(iname);
|
||||
m_objectToSelect = -1;
|
||||
}
|
||||
|
||||
@@ -780,12 +770,11 @@ void QmlInspectorAgent::addObjectToTree(const ObjectReference &obj,
|
||||
// find parent
|
||||
QTC_ASSERT(m_debugIdToIname.contains(parentId), break);
|
||||
QByteArray iname = m_debugIdToIname.value(parentId);
|
||||
const WatchData *parent = m_engine->watchHandler()->findItem(iname);
|
||||
WatchHandler *handler = m_engine->watchHandler();
|
||||
const WatchData *parent = handler->findData(iname);
|
||||
if (parent) {
|
||||
QList<WatchData> watches = buildWatchData(obj, *parent);
|
||||
m_engine->watchHandler()->beginCycle(false);
|
||||
m_engine->watchHandler()->insertBulkData(watches);
|
||||
m_engine->watchHandler()->endCycle();
|
||||
handler->insertData(watches);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@@ -153,6 +153,7 @@ private:
|
||||
DebugIdHash m_debugIdHash;
|
||||
|
||||
QList<int> m_objectWatches;
|
||||
QList<int> m_fetchDataIds;
|
||||
};
|
||||
|
||||
} // Internal
|
||||
|
@@ -272,7 +272,7 @@ void QmlV8DebuggerClientPrivate::evaluate(const QString expr, bool global,
|
||||
QScriptValue ctxtList = parser.call(QScriptValue(), QScriptValueList() << _(ARRAY ));
|
||||
while (rowCount) {
|
||||
QModelIndex index = localsModel->index(--rowCount, 0);
|
||||
const WatchData *data = engine->watchHandler()->watchData(LocalsWatch, index);
|
||||
const WatchData *data = engine->watchHandler()->watchData(index);
|
||||
QScriptValue ctxt = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT)));
|
||||
ctxt.setProperty(_(NAME), QScriptValue(data->name));
|
||||
ctxt.setProperty(_(HANDLE), QScriptValue(int(data->id)));
|
||||
@@ -1173,7 +1173,7 @@ void QmlV8DebuggerClient::expandObject(const QByteArray &iname, quint64 objectId
|
||||
{
|
||||
if (objectId == 0) {
|
||||
//We may have got the global object
|
||||
const WatchData *watch = d->engine->watchHandler()->findItem(iname);
|
||||
const WatchData *watch = d->engine->watchHandler()->findData(iname);
|
||||
if (watch->value == QLatin1String("global")) {
|
||||
StackHandler *stackHandler = d->engine->stackHandler();
|
||||
if (stackHandler->isContentsValid() && stackHandler->currentFrame().isUsable()) {
|
||||
@@ -1706,9 +1706,7 @@ void QmlV8DebuggerClient::setCurrentFrameDetails(const QVariant &bodyVal, const
|
||||
data.setHasChildren(true);
|
||||
data.id = 0;
|
||||
}
|
||||
d->engine->watchHandler()->beginCycle();
|
||||
d->engine->watchHandler()->insertData(data);
|
||||
d->engine->watchHandler()->endCycle();
|
||||
}
|
||||
|
||||
const QVariantList currentFrameScopes = currentFrame.value(_("scopes")).toList();
|
||||
@@ -1785,11 +1783,8 @@ void QmlV8DebuggerClient::updateScope(const QVariant &bodyVal, const QVariant &r
|
||||
if (!handlesToLookup.isEmpty())
|
||||
d->lookup(handlesToLookup);
|
||||
|
||||
if (!locals.isEmpty()) {
|
||||
d->engine->watchHandler()->beginCycle(false);
|
||||
d->engine->watchHandler()->insertBulkData(locals);
|
||||
d->engine->watchHandler()->endCycle();
|
||||
}
|
||||
if (!locals.isEmpty())
|
||||
d->engine->watchHandler()->insertData(locals);
|
||||
}
|
||||
|
||||
void QmlV8DebuggerClient::updateEvaluationResult(int sequence, bool success, const QVariant &bodyVal,
|
||||
@@ -1810,7 +1805,7 @@ void QmlV8DebuggerClient::updateEvaluationResult(int sequence, bool success, con
|
||||
d->scope(index);
|
||||
//Also update "this"
|
||||
QByteArray iname("local.this");
|
||||
const WatchData *parent = d->engine->watchHandler()->findItem(iname);
|
||||
const WatchData *parent = d->engine->watchHandler()->findData(iname);
|
||||
d->localsAndWatchers.insertMulti(parent->id, iname);
|
||||
d->lookup(QList<int>() << parent->id);
|
||||
|
||||
@@ -1833,7 +1828,7 @@ void QmlV8DebuggerClient::updateEvaluationResult(int sequence, bool success, con
|
||||
WatchData data;
|
||||
//Do we have request to evaluate a local?
|
||||
if (exp.startsWith("local.")) {
|
||||
const WatchData *watch = d->engine->watchHandler()->findItem(exp.toLatin1());
|
||||
const WatchData *watch = d->engine->watchHandler()->findData(exp.toLatin1());
|
||||
watchDataList << createWatchDataList(watch, body.properties, refsVal);
|
||||
} else {
|
||||
QByteArray iname = d->engine->watchHandler()->watcherName(exp.toLatin1());
|
||||
@@ -1854,9 +1849,7 @@ void QmlV8DebuggerClient::updateEvaluationResult(int sequence, bool success, con
|
||||
watchDataList << data << createWatchDataList(&data, body.properties, refsVal);
|
||||
}
|
||||
//Insert the newly evaluated expression to the Watchers Window
|
||||
d->engine->watchHandler()->beginCycle(false);
|
||||
d->engine->watchHandler()->insertBulkData(watchDataList);
|
||||
d->engine->watchHandler()->endCycle();
|
||||
d->engine->watchHandler()->insertData(watchDataList);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1933,7 +1926,7 @@ void QmlV8DebuggerClient::expandLocalsAndWatchers(const QVariant &bodyVal, const
|
||||
if (prepend.startsWith("local.") || prepend.startsWith("watch.")) {
|
||||
//Data for expanded local/watch
|
||||
//Could be an object or function
|
||||
const WatchData *parent = d->engine->watchHandler()->findItem(prepend);
|
||||
const WatchData *parent = d->engine->watchHandler()->findData(prepend);
|
||||
watchDataList << createWatchDataList(parent, bodyObjectData.properties, refsVal);
|
||||
} else {
|
||||
//rest
|
||||
@@ -1952,9 +1945,7 @@ void QmlV8DebuggerClient::expandLocalsAndWatchers(const QVariant &bodyVal, const
|
||||
}
|
||||
}
|
||||
|
||||
d->engine->watchHandler()->beginCycle(false);
|
||||
d->engine->watchHandler()->insertBulkData(watchDataList);
|
||||
d->engine->watchHandler()->endCycle();
|
||||
d->engine->watchHandler()->insertData(watchDataList);
|
||||
}
|
||||
|
||||
QList<WatchData> QmlV8DebuggerClient::createWatchDataList(const WatchData *parent,
|
||||
|
@@ -403,6 +403,8 @@ void QScriptDebuggerClient::messageReceived(const QByteArray &data)
|
||||
QByteArray command;
|
||||
stream >> command;
|
||||
|
||||
WatchHandler *watchHandler = d->engine->watchHandler();
|
||||
|
||||
if (command == "STOPPED") {
|
||||
d->engine->inferiorSpontaneousStop();
|
||||
|
||||
@@ -432,15 +434,13 @@ void QScriptDebuggerClient::messageReceived(const QByteArray &data)
|
||||
|
||||
d->engine->stackHandler()->setFrames(ideStackFrames);
|
||||
|
||||
d->engine->watchHandler()->beginCycle();
|
||||
bool needPing = false;
|
||||
|
||||
foreach (WatchData data, watches) {
|
||||
data.iname = d->engine->watchHandler()->watcherName(data.exp);
|
||||
d->engine->watchHandler()->insertData(data);
|
||||
data.iname = watchHandler->watcherName(data.exp);
|
||||
watchHandler->insertIncompleteData(data);
|
||||
|
||||
if (d->engine->watchHandler()->expandedINames().contains(data.iname) &&
|
||||
qint64(data.id) != -1) {
|
||||
if (watchHandler->isExpandedIName(data.iname) && qint64(data.id) != -1) {
|
||||
needPing = true;
|
||||
expandObject(data.iname,data.id);
|
||||
}
|
||||
@@ -448,20 +448,16 @@ void QScriptDebuggerClient::messageReceived(const QByteArray &data)
|
||||
|
||||
foreach (WatchData data, locals) {
|
||||
data.iname = "local." + data.exp;
|
||||
d->engine->watchHandler()->insertData(data);
|
||||
watchHandler->insertIncompleteData(data);
|
||||
|
||||
if (d->engine->watchHandler()->expandedINames().contains(data.iname) &&
|
||||
qint64(data.id) != -1) {
|
||||
if (watchHandler->isExpandedIName(data.iname) && qint64(data.id) != -1) {
|
||||
needPing = true;
|
||||
expandObject(data.iname,data.id);
|
||||
}
|
||||
}
|
||||
|
||||
if (needPing) {
|
||||
if (needPing)
|
||||
sendPing();
|
||||
} else {
|
||||
d->engine->watchHandler()->endCycle();
|
||||
}
|
||||
|
||||
bool becauseOfException;
|
||||
stream >> becauseOfException;
|
||||
@@ -518,12 +514,12 @@ void QScriptDebuggerClient::messageReceived(const QByteArray &data)
|
||||
+ QLatin1String(iname) + QLatin1Char(' ') + data.value);
|
||||
data.iname = iname;
|
||||
if (iname.startsWith("watch.")) {
|
||||
d->engine->watchHandler()->insertData(data);
|
||||
watchHandler->insertIncompleteData(data);
|
||||
} else if (iname == "console") {
|
||||
d->engine->showMessage(data.value, QtMessageLogOutput);
|
||||
} else if (iname.startsWith("local.")) {
|
||||
data.name = data.name.left(data.name.indexOf(QLatin1Char(' ')));
|
||||
d->engine->watchHandler()->insertData(data);
|
||||
watchHandler->insertIncompleteData(data);
|
||||
} else {
|
||||
qWarning() << "QmlEngine: Unexcpected result: " << iname << data.value;
|
||||
}
|
||||
@@ -538,10 +534,9 @@ void QScriptDebuggerClient::messageReceived(const QByteArray &data)
|
||||
|
||||
foreach (WatchData data, result) {
|
||||
data.iname = iname + '.' + data.exp;
|
||||
d->engine->watchHandler()->insertData(data);
|
||||
watchHandler->insertIncompleteData(data);
|
||||
|
||||
if (d->engine->watchHandler()->expandedINames().contains(data.iname) &&
|
||||
qint64(data.id) != -1) {
|
||||
if (watchHandler->isExpandedIName(data.iname) && qint64(data.id) != -1) {
|
||||
needPing = true;
|
||||
expandObject(data.iname, data.id);
|
||||
}
|
||||
@@ -560,14 +555,12 @@ void QScriptDebuggerClient::messageReceived(const QByteArray &data)
|
||||
d->logReceiveMessage(QString::fromLatin1("%1 %2 (%3 x locals) (%4 x watchdata)").arg(
|
||||
QLatin1String(command), QString::number(frameId),
|
||||
QString::number(locals.size()), QString::number(watches.size())));
|
||||
d->engine->watchHandler()->beginCycle();
|
||||
bool needPing = false;
|
||||
foreach (WatchData data, watches) {
|
||||
data.iname = d->engine->watchHandler()->watcherName(data.exp);
|
||||
d->engine->watchHandler()->insertData(data);
|
||||
data.iname = watchHandler->watcherName(data.exp);
|
||||
watchHandler->insertIncompleteData(data);
|
||||
|
||||
if (d->engine->watchHandler()->expandedINames().contains(data.iname) &&
|
||||
qint64(data.id) != -1) {
|
||||
if (watchHandler->isExpandedIName(data.iname) && qint64(data.id) != -1) {
|
||||
needPing = true;
|
||||
expandObject(data.iname, data.id);
|
||||
}
|
||||
@@ -575,26 +568,19 @@ void QScriptDebuggerClient::messageReceived(const QByteArray &data)
|
||||
|
||||
foreach (WatchData data, locals) {
|
||||
data.iname = "local." + data.exp;
|
||||
d->engine->watchHandler()->insertData(data);
|
||||
if (d->engine->watchHandler()->expandedINames().contains(data.iname) &&
|
||||
qint64(data.id) != -1) {
|
||||
watchHandler->insertIncompleteData(data);
|
||||
if (watchHandler->isExpandedIName(data.iname) && qint64(data.id) != -1) {
|
||||
needPing = true;
|
||||
expandObject(data.iname, data.id);
|
||||
}
|
||||
}
|
||||
if (needPing)
|
||||
sendPing();
|
||||
else
|
||||
d->engine->watchHandler()->endCycle();
|
||||
|
||||
} else if (command == "PONG") {
|
||||
int ping;
|
||||
stream >> ping;
|
||||
|
||||
d->logReceiveMessage(QLatin1String(command) + QLatin1Char(' ') + QString::number(ping));
|
||||
|
||||
if (ping == d->ping)
|
||||
d->engine->watchHandler()->endCycle();
|
||||
} else {
|
||||
qDebug() << Q_FUNC_INFO << "Unknown command: " << command;
|
||||
d->logReceiveMessage(QLatin1String(command) + QLatin1String(" UNKNOWN COMMAND!!"));
|
||||
|
@@ -651,7 +651,6 @@ bool ScriptEngine::checkForBreakCondition(bool byFunction)
|
||||
void ScriptEngine::updateLocals()
|
||||
{
|
||||
QScriptContext *context = m_scriptEngine->currentContext();
|
||||
watchHandler()->beginCycle();
|
||||
SDEBUG(Q_FUNC_INFO);
|
||||
|
||||
//
|
||||
@@ -686,9 +685,7 @@ void ScriptEngine::updateLocals()
|
||||
data.iname = "local";
|
||||
data.name = _(data.iname);
|
||||
|
||||
watchHandler()->beginCycle();
|
||||
updateSubItem(data);
|
||||
watchHandler()->endCycle();
|
||||
// FIXME: Use an extra thread. This here is evil.
|
||||
m_stopped = true;
|
||||
showStatusMessage(tr("Stopped."), 5000);
|
||||
@@ -809,9 +806,9 @@ void ScriptEngine::updateSubItem(const WatchData &data0)
|
||||
}
|
||||
|
||||
SDEBUG(msgDebugInsert(data, children));
|
||||
watchHandler()->insertData(data);
|
||||
watchHandler()->insertIncompleteData(data);
|
||||
if (!children.isEmpty())
|
||||
watchHandler()->insertBulkData(children);
|
||||
watchHandler()->insertData(children);
|
||||
}
|
||||
|
||||
DebuggerEngine *createScriptEngine(const DebuggerStartParameters &sp)
|
||||
|
@@ -143,7 +143,6 @@ WatchData::WatchData() :
|
||||
size(0),
|
||||
bitpos(0),
|
||||
bitsize(0),
|
||||
generation(-1),
|
||||
hasChildren(false),
|
||||
valueEnabled(true),
|
||||
valueEditable(true),
|
||||
@@ -399,8 +398,6 @@ QString WatchData::toToolTip() const
|
||||
if (size)
|
||||
formatToolTipRow(str, tr("Static Object Size"), tr("%1 bytes").arg(size));
|
||||
formatToolTipRow(str, tr("Internal ID"), QLatin1String(iname));
|
||||
formatToolTipRow(str, tr("Generation"),
|
||||
QString::number(generation));
|
||||
str << "</table></body></html>";
|
||||
return res;
|
||||
}
|
||||
|
@@ -135,7 +135,6 @@ public:
|
||||
uint size; // Size
|
||||
uint bitpos; // Position within bit fields
|
||||
uint bitsize; // Size in case of bit fields
|
||||
qint32 generation; // When updated?
|
||||
bool hasChildren;
|
||||
bool valueEnabled; // Value will be enabled or not
|
||||
bool valueEditable; // Value will be editable
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -35,28 +35,38 @@
|
||||
|
||||
#include "watchdata.h"
|
||||
|
||||
#include <QPointer>
|
||||
#include <QHash>
|
||||
#include <QSet>
|
||||
#include <QStringList>
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
namespace Debugger {
|
||||
|
||||
class DebuggerEngine;
|
||||
|
||||
namespace Internal {
|
||||
|
||||
class WatchItem;
|
||||
class WatchHandler;
|
||||
class WatchModel;
|
||||
|
||||
class UpdateParameters
|
||||
{
|
||||
public:
|
||||
UpdateParameters() { tryPartial = tooltipOnly = false; }
|
||||
|
||||
bool tryPartial;
|
||||
bool tooltipOnly;
|
||||
QByteArray varList;
|
||||
};
|
||||
|
||||
typedef QHash<QString, QStringList> TypeFormats;
|
||||
|
||||
enum WatchType
|
||||
{
|
||||
ReturnWatch,
|
||||
LocalsWatch,
|
||||
WatchersWatch,
|
||||
TooltipsWatch,
|
||||
InspectWatch
|
||||
LocalsType,
|
||||
InspectType,
|
||||
WatchersType,
|
||||
ReturnType,
|
||||
TooltipType
|
||||
};
|
||||
|
||||
enum IntegerFormat
|
||||
@@ -67,126 +77,38 @@ enum IntegerFormat
|
||||
OctalFormat
|
||||
};
|
||||
|
||||
class WatchModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
explicit WatchModel(WatchHandler *handler, WatchType type);
|
||||
virtual ~WatchModel();
|
||||
|
||||
public:
|
||||
virtual int rowCount(const QModelIndex &idx = QModelIndex()) const;
|
||||
virtual int columnCount(const QModelIndex &idx) const;
|
||||
|
||||
signals:
|
||||
void setCurrentIndex(const QModelIndex &index);
|
||||
|
||||
private:
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||
QModelIndex index(int, int, const QModelIndex &idx) const;
|
||||
QModelIndex parent(const QModelIndex &idx) const;
|
||||
bool hasChildren(const QModelIndex &idx) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &idx) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const;
|
||||
bool canFetchMore(const QModelIndex &parent) const;
|
||||
void fetchMore(const QModelIndex &parent);
|
||||
|
||||
void invalidateAll(const QModelIndex &parentIndex = QModelIndex());
|
||||
|
||||
friend class WatchHandler;
|
||||
|
||||
WatchItem *watchItem(const QModelIndex &) const;
|
||||
QModelIndex watchIndex(const WatchItem *needle) const;
|
||||
QModelIndex watchIndexHelper(const WatchItem *needle,
|
||||
const WatchItem *parentItem, const QModelIndex &parentIndex) const;
|
||||
|
||||
void insertData(const WatchData &data);
|
||||
void reinsertAllData();
|
||||
void reinsertAllDataHelper(WatchItem *item, QList<WatchData> *data);
|
||||
void insertBulkData(const QList<WatchData> &data);
|
||||
WatchItem *findItem(const QByteArray &iname, WatchItem *root) const;
|
||||
QString displayForAutoTest(const QByteArray &iname) const;
|
||||
void reinitialize();
|
||||
void removeOutdated();
|
||||
void removeOutdatedHelper(WatchItem *item);
|
||||
WatchItem *rootItem() const;
|
||||
void destroyItem(WatchItem *item);
|
||||
|
||||
void emitDataChanged(int column,
|
||||
const QModelIndex &parentIndex = QModelIndex());
|
||||
void beginCycle(bool fullCycle); // Called at begin of updateLocals() cycle.
|
||||
void endCycle(); // Called after all results have been received.
|
||||
|
||||
friend QDebug operator<<(QDebug d, const WatchModel &m);
|
||||
|
||||
void dump();
|
||||
void dumpHelper(WatchItem *item);
|
||||
void emitAllChanged();
|
||||
|
||||
private:
|
||||
QString displayType(const WatchData &typeIn) const;
|
||||
QString formattedValue(const WatchData &data) const;
|
||||
QString removeInitialNamespace(QString str) const;
|
||||
QString removeNamespaces(QString str) const;
|
||||
void formatRequests(QByteArray *out, const WatchItem *item) const;
|
||||
DebuggerEngine *engine() const;
|
||||
QString display(const WatchItem *item, int col) const;
|
||||
int itemFormat(const WatchData &data) const;
|
||||
bool contentIsValid() const;
|
||||
int m_generationCounter;
|
||||
|
||||
WatchHandler *m_handler;
|
||||
WatchType m_type;
|
||||
WatchItem *m_root;
|
||||
QSet<QByteArray> m_fetchTriggered;
|
||||
};
|
||||
|
||||
class WatchHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit WatchHandler(DebuggerEngine *engine);
|
||||
WatchModel *model(WatchType type) const;
|
||||
WatchModel *modelForIName(const QByteArray &iname) const;
|
||||
~WatchHandler();
|
||||
|
||||
QAbstractItemModel *model() const;
|
||||
|
||||
void cleanup();
|
||||
void watchExpression(const QString &exp);
|
||||
void removeWatchExpression(const QString &exp);
|
||||
Q_SLOT void clearWatches();
|
||||
Q_SLOT void emitAllChanged();
|
||||
|
||||
void beginCycle(bool fullCycle = true); // Called at begin of updateLocals() cycle
|
||||
void updateWatchers(); // Called after locals are fetched
|
||||
void endCycle(); // Called after all results have been received
|
||||
|
||||
void beginCycle(WatchType type, bool fullCycle = true);
|
||||
void endCycle(WatchType type);
|
||||
|
||||
void showEditValue(const WatchData &data);
|
||||
|
||||
void insertData(const WatchData &data);
|
||||
void insertBulkData(const QList<WatchData> &data);
|
||||
void removeData(const QByteArray &iname);
|
||||
Q_SLOT void reinsertAllData();
|
||||
|
||||
const WatchData *watchData(WatchType type, const QModelIndex &) const;
|
||||
const WatchData *findItem(const QByteArray &iname) const;
|
||||
const WatchData *watchData(const QModelIndex &) const;
|
||||
const WatchData *findData(const QByteArray &iname) const;
|
||||
QString displayForAutoTest(const QByteArray &iname) const;
|
||||
QModelIndex itemIndex(const QByteArray &iname) const;
|
||||
bool hasItem(const QByteArray &iname) const;
|
||||
|
||||
void loadSessionData();
|
||||
void saveSessionData();
|
||||
void removeTooltip();
|
||||
void rebuildModel();
|
||||
|
||||
bool isExpandedIName(const QByteArray &iname) const
|
||||
{ return m_expandedINames.contains(iname); }
|
||||
QSet<QByteArray> expandedINames() const
|
||||
{ return m_expandedINames; }
|
||||
bool isExpandedIName(const QByteArray &iname) const;
|
||||
QSet<QByteArray> expandedINames() const;
|
||||
|
||||
static QStringList watchedExpressions();
|
||||
static QHash<QByteArray, int> watcherNames();
|
||||
|
||||
@@ -199,7 +121,6 @@ public:
|
||||
void addTypeFormats(const QByteArray &type, const QStringList &formats);
|
||||
void setTypeFormats(const TypeFormats &typeFormats);
|
||||
TypeFormats typeFormats() const;
|
||||
QStringList typeFormatList(const WatchData &data) const;
|
||||
|
||||
void setUnprintableBase(int base);
|
||||
static int unprintableBase();
|
||||
@@ -213,7 +134,15 @@ public:
|
||||
void resetLocation();
|
||||
bool isValidToolTip(const QByteArray &iname) const;
|
||||
|
||||
void setCurrentModelIndex(WatchType modelType, const QModelIndex &index);
|
||||
void setCurrentItem(const QByteArray &iname);
|
||||
void updateWatchersWindow();
|
||||
|
||||
void insertData(const WatchData &data); // Convenience.
|
||||
void insertData(const QList<WatchData> &list);
|
||||
void insertIncompleteData(const WatchData &data);
|
||||
void removeData(const QByteArray &iname);
|
||||
void removeChildren(const QByteArray &iname);
|
||||
void removeAllData();
|
||||
|
||||
private:
|
||||
friend class WatchModel;
|
||||
@@ -223,25 +152,8 @@ private:
|
||||
static void saveTypeFormats();
|
||||
|
||||
void setFormat(const QByteArray &type, int format);
|
||||
void updateWatchersWindow();
|
||||
void showInEditorHelper(QString *contents, WatchItem *item, int level);
|
||||
|
||||
bool m_inChange;
|
||||
|
||||
// QWidgets and QProcesses taking care of special displays.
|
||||
typedef QMap<QByteArray, QPointer<QObject> > EditHandlers;
|
||||
EditHandlers m_editHandlers;
|
||||
|
||||
TypeFormats m_reportedTypeFormats;
|
||||
|
||||
// Items expanded in the Locals & Watchers view.
|
||||
QSet<QByteArray> m_expandedINames;
|
||||
|
||||
WatchModel *m_return;
|
||||
WatchModel *m_locals;
|
||||
WatchModel *m_watchers;
|
||||
WatchModel *m_tooltips;
|
||||
WatchModel *m_inspect;
|
||||
WatchModel *m_model;
|
||||
DebuggerEngine *m_engine;
|
||||
|
||||
int m_watcherCounter;
|
||||
@@ -253,4 +165,6 @@ private:
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
Q_DECLARE_METATYPE(Debugger::Internal::UpdateParameters)
|
||||
|
||||
#endif // DEBUGGER_WATCHHANDLER_H
|
||||
|
@@ -530,12 +530,12 @@ void WatchTreeView::keyPressEvent(QKeyEvent *ev)
|
||||
QString exp = model()->data(idx1).toString();
|
||||
watchExpression(exp);
|
||||
}
|
||||
QTreeView::keyPressEvent(ev);
|
||||
BaseTreeView::keyPressEvent(ev);
|
||||
}
|
||||
|
||||
void WatchTreeView::dragEnterEvent(QDragEnterEvent *ev)
|
||||
{
|
||||
//QTreeView::dragEnterEvent(ev);
|
||||
//BaseTreeView::dragEnterEvent(ev);
|
||||
if (ev->mimeData()->hasText()) {
|
||||
ev->setDropAction(Qt::CopyAction);
|
||||
ev->accept();
|
||||
@@ -544,7 +544,7 @@ void WatchTreeView::dragEnterEvent(QDragEnterEvent *ev)
|
||||
|
||||
void WatchTreeView::dragMoveEvent(QDragMoveEvent *ev)
|
||||
{
|
||||
//QTreeView::dragMoveEvent(ev);
|
||||
//BaseTreeView::dragMoveEvent(ev);
|
||||
if (ev->mimeData()->hasText()) {
|
||||
ev->setDropAction(Qt::CopyAction);
|
||||
ev->accept();
|
||||
@@ -559,7 +559,7 @@ void WatchTreeView::dropEvent(QDropEvent *ev)
|
||||
ev->setDropAction(Qt::CopyAction);
|
||||
ev->accept();
|
||||
}
|
||||
//QTreeView::dropEvent(ev);
|
||||
//BaseTreeView::dropEvent(ev);
|
||||
}
|
||||
|
||||
void WatchTreeView::mouseDoubleClickEvent(QMouseEvent *ev)
|
||||
@@ -570,7 +570,7 @@ void WatchTreeView::mouseDoubleClickEvent(QMouseEvent *ev)
|
||||
watchExpression(QString());
|
||||
return;
|
||||
}
|
||||
QTreeView::mouseDoubleClickEvent(ev);
|
||||
BaseTreeView::mouseDoubleClickEvent(ev);
|
||||
}
|
||||
|
||||
// Text for add watch action with truncated expression.
|
||||
@@ -971,7 +971,7 @@ bool WatchTreeView::event(QEvent *ev)
|
||||
releaseMouse();
|
||||
currentEngine()->watchPoint(mapToGlobal(mev->pos()));
|
||||
}
|
||||
return QTreeView::event(ev);
|
||||
return BaseTreeView::event(ev);
|
||||
}
|
||||
|
||||
void WatchTreeView::editItem(const QModelIndex &idx)
|
||||
@@ -982,6 +982,7 @@ void WatchTreeView::editItem(const QModelIndex &idx)
|
||||
void WatchTreeView::setModel(QAbstractItemModel *model)
|
||||
{
|
||||
BaseTreeView::setModel(model);
|
||||
setRootIndex(model->index(m_type, 0, QModelIndex()));
|
||||
setRootIsDecorated(true);
|
||||
if (header()) {
|
||||
header()->setDefaultAlignment(Qt::AlignLeft);
|
||||
@@ -990,15 +991,25 @@ void WatchTreeView::setModel(QAbstractItemModel *model)
|
||||
}
|
||||
|
||||
connect(model, SIGNAL(layoutChanged()), SLOT(resetHelper()));
|
||||
|
||||
QTC_ASSERT(qobject_cast<WatchModel*>(model), return);
|
||||
connect(model, SIGNAL(setCurrentIndex(QModelIndex)),
|
||||
connect(model, SIGNAL(currentIndexRequested(QModelIndex)),
|
||||
SLOT(setCurrentIndex(QModelIndex)));
|
||||
connect(model, SIGNAL(itemIsExpanded(QModelIndex)),
|
||||
SLOT(handleItemIsExpanded(QModelIndex)));
|
||||
}
|
||||
|
||||
void WatchTreeView::handleItemIsExpanded(const QModelIndex &idx)
|
||||
{
|
||||
bool on = idx.data(LocalsExpandedRole).toBool();
|
||||
QTC_ASSERT(on, return);
|
||||
if (!isExpanded(idx))
|
||||
expand(idx);
|
||||
}
|
||||
|
||||
void WatchTreeView::resetHelper()
|
||||
{
|
||||
resetHelper(model()->index(0, 0));
|
||||
QModelIndex idx = model()->index(m_type, 0);
|
||||
resetHelper(idx);
|
||||
expand(idx);
|
||||
}
|
||||
|
||||
void WatchTreeView::resetHelper(const QModelIndex &idx)
|
||||
@@ -1019,6 +1030,13 @@ void WatchTreeView::resetHelper(const QModelIndex &idx)
|
||||
}
|
||||
}
|
||||
|
||||
void WatchTreeView::reset()
|
||||
{
|
||||
BaseTreeView::reset();
|
||||
setRootIndex(model()->index(m_type, 0));
|
||||
resetHelper();
|
||||
}
|
||||
|
||||
void WatchTreeView::watchExpression(const QString &exp)
|
||||
{
|
||||
currentEngine()->watchHandler()->watchExpression(exp);
|
||||
@@ -1063,7 +1081,5 @@ void WatchTreeView::setWatchpointAtExpression(const QString &exp)
|
||||
breakHandler()->appendBreakpoint(data);
|
||||
}
|
||||
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
|
@@ -49,15 +49,17 @@ class WatchTreeView : public BaseTreeView
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Type { ReturnType, LocalsType, TooltipType, WatchersType, InspectType };
|
||||
enum Type { LocalsType, InspectType, WatchersType, ReturnType, TooltipType };
|
||||
|
||||
explicit WatchTreeView(Type type, QWidget *parent = 0);
|
||||
Type type() const { return m_type; }
|
||||
void setModel(QAbstractItemModel *model);
|
||||
void reset();
|
||||
|
||||
public slots:
|
||||
void watchExpression(const QString &exp);
|
||||
void removeWatchExpression(const QString &exp);
|
||||
void handleItemIsExpanded(const QModelIndex &idx);
|
||||
|
||||
private:
|
||||
Q_SLOT void resetHelper();
|
||||
|
Reference in New Issue
Block a user