Debugger: Remove most remaining occurrences of WatchData

... in WatchHandler and DebuggerEngine interface.
Adjust using code.

Change-Id: I6371f3e96ba46a783e23a5767cdde24a10d3fce7
Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
Reviewed-by: hjk <hjk@theqtcompany.com>
This commit is contained in:
hjk
2015-03-19 12:42:53 +01:00
parent b08e5a9bc3
commit b3f88df41d
28 changed files with 468 additions and 568 deletions

View File

@@ -67,7 +67,7 @@ def qdump__Debugger__Internal__WatchData(d, value):
d.putPlainChildren(value) d.putPlainChildren(value)
def qdump__Debugger__Internal__WatchItem(d, value): def qdump__Debugger__Internal__WatchItem(d, value):
d.putByteArrayValue(value["d"]["iname"]) d.putByteArrayValue(value["iname"])
d.putPlainChildren(value) d.putPlainChildren(value)
def qdump__Debugger__Internal__BreakpointModelId(d, value): def qdump__Debugger__Internal__BreakpointModelId(d, value):

View File

@@ -725,6 +725,17 @@ void TreeItem::removeChildren()
} }
} }
void TreeItem::sortChildren(const std::function<bool(const TreeItem *, const TreeItem *)> &cmp)
{
if (m_model) {
m_model->layoutAboutToBeChanged();
std::sort(m_children.begin(), m_children.end(), cmp);
m_model->layoutChanged();
} else {
std::sort(m_children.begin(), m_children.end(), cmp);
}
}
void TreeItem::update() void TreeItem::update()
{ {
if (m_model) { if (m_model) {

View File

@@ -88,6 +88,7 @@ public:
void appendChild(TreeItem *item); void appendChild(TreeItem *item);
void insertChild(int pos, TreeItem *item); void insertChild(int pos, TreeItem *item);
void removeChildren(); void removeChildren();
void sortChildren(const std::function<bool(const TreeItem *, const TreeItem *)> &cmp);
void update(); void update();
void updateColumn(int column); void updateColumn(int column);
void expand(); void expand();

View File

@@ -974,46 +974,47 @@ static inline bool isWatchIName(const QByteArray &iname)
return iname.startsWith("watch"); return iname.startsWith("watch");
} }
void CdbEngine::updateWatchData(const WatchData &dataIn) void CdbEngine::updateWatchItem(WatchItem *item)
{ {
if (debug || debugLocals || debugWatches) if (debug || debugLocals || debugWatches)
qDebug("CdbEngine::updateWatchData() %dms accessible=%d %s: %s", qDebug("CdbEngine::updateWatchData() %dms accessible=%d %s: %s",
elapsedLogTime(), m_accessible, stateName(state()), elapsedLogTime(), m_accessible, stateName(state()),
qPrintable(dataIn.toString())); qPrintable(item->toString()));
if (!m_accessible) // Add watch data while running? if (!m_accessible) // Add watch data while running?
return; return;
// New watch item? // New watch item?
if (dataIn.isWatcher() && dataIn.isValueNeeded()) { if (item->isWatcher() && item->isValueNeeded()) {
QByteArray args; QByteArray args;
ByteArrayInputStream str(args); ByteArrayInputStream str(args);
str << dataIn.iname << " \"" << dataIn.exp << '"'; WatchData data = *item; // Don't pass pointers to async functions.
str << data.iname << " \"" << data.exp << '"';
postExtensionCommand("addwatch", args, 0, postExtensionCommand("addwatch", args, 0,
[this, dataIn](const CdbResponse &r) { handleAddWatch(r, dataIn); }); [this, data](const CdbResponse &r) { handleAddWatch(r, data); });
return; return;
} }
if (!dataIn.hasChildren && !dataIn.isValueNeeded()) { if (item->wantsChildren || item->isValueNeeded()) {
WatchData data = dataIn; updateLocalVariable(item->iname);
data.setAllUnneeded(); } else {
watchHandler()->insertData(data); item->setAllUnneeded();
return; item->update();
} }
updateLocalVariable(dataIn.iname);
} }
void CdbEngine::handleAddWatch(const CdbResponse &response, WatchData item) void CdbEngine::handleAddWatch(const CdbResponse &response, WatchData data)
{ {
if (debugWatches) if (debugWatches)
qDebug() << "handleAddWatch ok=" << response.success << item.iname; qDebug() << "handleAddWatch ok=" << response.success << data.iname;
if (response.success) { if (response.success) {
updateLocalVariable(item.iname); updateLocalVariable(data.iname);
} else { } else {
item.setError(tr("Unable to add expression")); auto item = new WatchItem(data);
watchHandler()->insertData(item); item->setError(tr("Unable to add expression"));
watchHandler()->insertItem(item);
showMessage(QString::fromLatin1("Unable to add watch item \"%1\"/\"%2\": %3"). showMessage(QString::fromLatin1("Unable to add watch item \"%1\"/\"%2\": %3").
arg(QString::fromLatin1(item.iname), QString::fromLatin1(item.exp), arg(QString::fromLatin1(data.iname), QString::fromLatin1(data.exp),
QString::fromLocal8Bit(response.errorMessage)), LogError); QString::fromLocal8Bit(response.errorMessage)), LogError);
} }
} }
@@ -1269,7 +1270,7 @@ static inline bool isAsciiWord(const QString &s)
return true; return true;
} }
void CdbEngine::assignValueInDebugger(const WatchData *w, const QString &expr, const QVariant &value) void CdbEngine::assignValueInDebugger(WatchItem *w, const QString &expr, const QVariant &value)
{ {
if (debug) if (debug)
qDebug() << "CdbEngine::assignValueInDebugger" << w->iname << expr << value; qDebug() << "CdbEngine::assignValueInDebugger" << w->iname << expr << value;
@@ -1871,13 +1872,13 @@ void CdbEngine::handleLocals(const CdbResponse &response, bool newFrame)
QSet<QByteArray> toDelete; QSet<QByteArray> toDelete;
if (newFrame) { if (newFrame) {
foreach (WatchItem *item, handler->model()->treeLevelItems<WatchItem *>(2)) foreach (WatchItem *item, handler->model()->treeLevelItems<WatchItem *>(2))
toDelete.insert(item->d.iname); toDelete.insert(item->iname);
} }
foreach (const GdbMi &child, all.children()) { foreach (const GdbMi &child, all.children()) {
WatchItem *item = new WatchItem(child); WatchItem *item = new WatchItem(child);
handler->insertItem(item); handler->insertItem(item);
toDelete.remove(item->d.iname); toDelete.remove(item->iname);
} }
handler->purgeOutdatedItems(toDelete); handler->purgeOutdatedItems(toDelete);

View File

@@ -89,7 +89,7 @@ public:
virtual void shutdownEngine(); virtual void shutdownEngine();
virtual void abortDebugger(); virtual void abortDebugger();
virtual void detachDebugger(); virtual void detachDebugger();
virtual void updateWatchData(const WatchData &data); virtual void updateWatchItem(WatchItem *item);
virtual bool hasCapability(unsigned cap) const; virtual bool hasCapability(unsigned cap) const;
virtual void watchPoint(const QPoint &); virtual void watchPoint(const QPoint &);
virtual void setRegisterValue(const QByteArray &name, const QString &value); virtual void setRegisterValue(const QByteArray &name, const QString &value);
@@ -106,7 +106,7 @@ public:
virtual void executeRunToLine(const ContextData &data); virtual void executeRunToLine(const ContextData &data);
virtual void executeRunToFunction(const QString &functionName); virtual void executeRunToFunction(const QString &functionName);
virtual void executeJumpToLine(const ContextData &data); virtual void executeJumpToLine(const ContextData &data);
virtual void assignValueInDebugger(const WatchData *w, const QString &expr, const QVariant &value); virtual void assignValueInDebugger(WatchItem *w, const QString &expr, const QVariant &value);
virtual void executeDebuggerCommand(const QString &command, DebuggerLanguages languages); virtual void executeDebuggerCommand(const QString &command, DebuggerLanguages languages);
virtual void activateFrame(int index); virtual void activateFrame(int index);

View File

@@ -1439,10 +1439,6 @@ bool DebuggerEngine::setToolTipExpression(const DebuggerToolTipContext &)
return false; return false;
} }
void DebuggerEngine::updateWatchData(const WatchData &)
{
}
void DebuggerEngine::watchDataSelected(const QByteArray &) void DebuggerEngine::watchDataSelected(const QByteArray &)
{ {
} }
@@ -1635,7 +1631,7 @@ void DebuggerEngine::changeBreakpoint(Breakpoint bp)
QTC_CHECK(false); QTC_CHECK(false);
} }
void DebuggerEngine::assignValueInDebugger(const WatchData *, void DebuggerEngine::assignValueInDebugger(WatchItem *,
const QString &, const QVariant &) const QString &, const QVariant &)
{ {
} }

View File

@@ -62,6 +62,7 @@ class DebuggerPluginPrivate;
class DisassemblerAgent; class DisassemblerAgent;
class MemoryAgent; class MemoryAgent;
class WatchData; class WatchData;
class WatchItem;
class BreakHandler; class BreakHandler;
class ModulesHandler; class ModulesHandler;
class RegisterHandler; class RegisterHandler;
@@ -139,7 +140,7 @@ public:
virtual bool setToolTipExpression(const Internal::DebuggerToolTipContext &); virtual bool setToolTipExpression(const Internal::DebuggerToolTipContext &);
virtual void updateWatchData(const Internal::WatchData &data); virtual void updateWatchItem(WatchItem *) {}
virtual void watchDataSelected(const QByteArray &iname); virtual void watchDataSelected(const QByteArray &iname);
virtual void startDebugger(DebuggerRunControl *runControl); virtual void startDebugger(DebuggerRunControl *runControl);
@@ -198,7 +199,7 @@ public:
virtual bool acceptsDebuggerCommands() const { return true; } virtual bool acceptsDebuggerCommands() const { return true; }
virtual void executeDebuggerCommand(const QString &command, DebuggerLanguages languages); virtual void executeDebuggerCommand(const QString &command, DebuggerLanguages languages);
virtual void assignValueInDebugger(const Internal::WatchData *data, virtual void assignValueInDebugger(WatchItem *item,
const QString &expr, const QVariant &value); const QString &expr, const QVariant &value);
virtual void selectThread(Internal::ThreadId threadId) = 0; virtual void selectThread(Internal::ThreadId threadId) = 0;

View File

@@ -218,9 +218,9 @@ ToolTipWatchItem::ToolTipWatchItem(WatchItem *item)
name = item->displayName(); name = item->displayName();
value = item->displayValue(); value = item->displayValue();
type = item->displayType(); type = item->displayType();
iname = item->d.iname; iname = item->iname;
valueColor = item->valueColor(); valueColor = item->valueColor();
expandable = item->d.hasChildren; expandable = item->hasChildren();
expression = item->expression(); expression = item->expression();
foreach (TreeItem *child, item->children()) foreach (TreeItem *child, item->children())
appendChild(new ToolTipWatchItem(static_cast<WatchItem *>(child))); appendChild(new ToolTipWatchItem(static_cast<WatchItem *>(child)));

View File

@@ -3724,11 +3724,11 @@ void GdbEngine::reloadLocals()
updateLocals(); updateLocals();
} }
void GdbEngine::updateWatchData(const WatchData &data) void GdbEngine::updateWatchItem(WatchItem *item)
{ {
UpdateParameters params; UpdateParameters params;
params.tryPartial = m_pendingBreakpointRequests == 0; params.tryPartial = m_pendingBreakpointRequests == 0;
params.varList = data.iname; params.varList = item->iname;
updateLocalsPython(params); updateLocalsPython(params);
} }
@@ -3759,14 +3759,14 @@ void GdbEngine::updateLocals()
updateLocalsPython(UpdateParameters()); updateLocalsPython(UpdateParameters());
} }
void GdbEngine::assignValueInDebugger(const WatchData *data, void GdbEngine::assignValueInDebugger(WatchItem *item,
const QString &expression, const QVariant &value) const QString &expression, const QVariant &value)
{ {
DebuggerCommand cmd("assignValue"); DebuggerCommand cmd("assignValue");
cmd.arg("type", data->type.toHex()); cmd.arg("type", item->type.toHex());
cmd.arg("expr", expression.toLatin1().toHex()); cmd.arg("expr", expression.toLatin1().toHex());
cmd.arg("value", value.toString().toLatin1().toHex()); cmd.arg("value", value.toString().toLatin1().toHex());
cmd.arg("simpleType", isIntOrFloatType(data->type)); cmd.arg("simpleType", isIntOrFloatType(item->type));
cmd.callback = CB(handleVarAssign); cmd.callback = CB(handleVarAssign);
runCommand(cmd); runCommand(cmd);
} }
@@ -4805,17 +4805,17 @@ void GdbEngine::handleStackFramePython(const DebuggerResponse &response, bool pa
QSet<QByteArray> toDelete; QSet<QByteArray> toDelete;
if (!partial) { if (!partial) {
foreach (WatchItem *item, handler->model()->treeLevelItems<WatchItem *>(2)) foreach (WatchItem *item, handler->model()->treeLevelItems<WatchItem *>(2))
toDelete.insert(item->d.iname); toDelete.insert(item->iname);
} }
foreach (const GdbMi &child, data.children()) { foreach (const GdbMi &child, data.children()) {
WatchItem *item = new WatchItem(child); WatchItem *item = new WatchItem(child);
const TypeInfo ti = m_typeInfoCache.value(item->d.type); const TypeInfo ti = m_typeInfoCache.value(item->type);
if (ti.size) if (ti.size)
item->d.size = ti.size; item->size = ti.size;
handler->insertItem(item); handler->insertItem(item);
toDelete.remove(item->d.iname); toDelete.remove(item->iname);
} }
handler->purgeOutdatedItems(toDelete); handler->purgeOutdatedItems(toDelete);

View File

@@ -59,7 +59,6 @@ class MemoryAgentCookie;
class BreakpointParameters; class BreakpointParameters;
class BreakpointResponse; class BreakpointResponse;
class WatchData;
class DisassemblerAgentCookie; class DisassemblerAgentCookie;
class DisassemblerLines; class DisassemblerLines;
@@ -384,7 +383,7 @@ protected:
// Watch specific stuff // Watch specific stuff
// //
virtual bool setToolTipExpression(const DebuggerToolTipContext &); virtual bool setToolTipExpression(const DebuggerToolTipContext &);
virtual void assignValueInDebugger(const WatchData *data, virtual void assignValueInDebugger(WatchItem *item,
const QString &expr, const QVariant &value); const QString &expr, const QVariant &value);
virtual void fetchMemory(MemoryAgent *agent, QObject *token, virtual void fetchMemory(MemoryAgent *agent, QObject *token,
@@ -398,8 +397,8 @@ protected:
virtual void watchPoint(const QPoint &); virtual void watchPoint(const QPoint &);
void handleWatchPoint(const DebuggerResponse &response); void handleWatchPoint(const DebuggerResponse &response);
void updateWatchData(const WatchData &data);
void rebuildWatchModel(); void rebuildWatchModel();
void updateWatchItem(WatchItem *item);
void showToolTip(); void showToolTip();
void handleVarAssign(const DebuggerResponse &response); void handleVarAssign(const DebuggerResponse &response);

View File

@@ -844,19 +844,17 @@ void LldbEngine::reloadFullStack()
// //
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void LldbEngine::assignValueInDebugger(const Internal::WatchData *data, void LldbEngine::assignValueInDebugger(WatchItem *,
const QString &expression, const QVariant &value) const QString &expression, const QVariant &value)
{ {
Q_UNUSED(data);
DebuggerCommand cmd("assignValue"); DebuggerCommand cmd("assignValue");
cmd.arg("exp", expression.toLatin1().toHex()); cmd.arg("exp", expression.toLatin1().toHex());
cmd.arg("value", value.toString().toLatin1().toHex()); cmd.arg("value", value.toString().toLatin1().toHex());
runCommand(cmd); runCommand(cmd);
} }
void LldbEngine::updateWatchData(const WatchData &data) void LldbEngine::updateWatchItem(WatchItem *)
{ {
Q_UNUSED(data);
updateLocals(); updateLocals();
} }
@@ -1001,12 +999,12 @@ void LldbEngine::refreshLocals(const GdbMi &vars)
QSet<QByteArray> toDelete; QSet<QByteArray> toDelete;
foreach (WatchItem *item, handler->model()->treeLevelItems<WatchItem *>(2)) foreach (WatchItem *item, handler->model()->treeLevelItems<WatchItem *>(2))
toDelete.insert(item->d.iname); toDelete.insert(item->iname);
foreach (const GdbMi &child, vars.children()) { foreach (const GdbMi &child, vars.children()) {
WatchItem *item = new WatchItem(child); WatchItem *item = new WatchItem(child);
handler->insertItem(item); handler->insertItem(item);
toDelete.remove(item->d.iname); toDelete.remove(item->iname);
} }
handler->purgeOutdatedItems(toDelete); handler->purgeOutdatedItems(toDelete);

View File

@@ -105,8 +105,7 @@ private:
void removeBreakpoint(Breakpoint bp); void removeBreakpoint(Breakpoint bp);
void changeBreakpoint(Breakpoint bp); void changeBreakpoint(Breakpoint bp);
void assignValueInDebugger(const WatchData *data, void assignValueInDebugger(WatchItem *item, const QString &expr, const QVariant &value);
const QString &expr, const QVariant &value);
void executeDebuggerCommand(const QString &command, DebuggerLanguages languages); void executeDebuggerCommand(const QString &command, DebuggerLanguages languages);
void loadSymbols(const QString &moduleName); void loadSymbols(const QString &moduleName);
@@ -122,7 +121,7 @@ private:
bool supportsThreads() const { return true; } bool supportsThreads() const { return true; }
bool isSynchronous() const { return true; } bool isSynchronous() const { return true; }
void updateWatchData(const WatchData &data); void updateWatchItem(WatchItem *item);
void setRegisterValue(const QByteArray &name, const QString &value); void setRegisterValue(const QByteArray &name, const QString &value);
void fetchMemory(Internal::MemoryAgent *, QObject *, quint64 addr, quint64 length); void fetchMemory(Internal::MemoryAgent *, QObject *, quint64 addr, quint64 length);

View File

@@ -382,7 +382,7 @@ bool PdbEngine::setToolTipExpression(const DebuggerToolTipContext &ctx)
return true; return true;
} }
void PdbEngine::assignValueInDebugger(const WatchData *, const QString &expression, const QVariant &value) void PdbEngine::assignValueInDebugger(WatchItem *, const QString &expression, const QVariant &value)
{ {
//DebuggerCommand cmd("assignValue"); //DebuggerCommand cmd("assignValue");
//cmd.arg("expression", expression); //cmd.arg("expression", expression);
@@ -393,9 +393,9 @@ void PdbEngine::assignValueInDebugger(const WatchData *, const QString &expressi
updateLocals(); updateLocals();
} }
void PdbEngine::updateWatchData(const WatchData &data) void PdbEngine::updateWatchItem(WatchItem *item)
{ {
Q_UNUSED(data); Q_UNUSED(item);
updateAll(); updateAll();
} }
@@ -573,12 +573,12 @@ void PdbEngine::refreshLocals(const GdbMi &vars)
QSet<QByteArray> toDelete; QSet<QByteArray> toDelete;
foreach (WatchItem *item, handler->model()->treeLevelItems<WatchItem *>(2)) foreach (WatchItem *item, handler->model()->treeLevelItems<WatchItem *>(2))
toDelete.insert(item->d.iname); toDelete.insert(item->iname);
foreach (const GdbMi &child, vars.children()) { foreach (const GdbMi &child, vars.children()) {
WatchItem *item = new WatchItem(child); WatchItem *item = new WatchItem(child);
handler->insertItem(item); handler->insertItem(item);
toDelete.remove(item->d.iname); toDelete.remove(item->iname);
} }
handler->purgeOutdatedItems(toDelete); handler->purgeOutdatedItems(toDelete);

View File

@@ -82,7 +82,7 @@ private:
void insertBreakpoint(Breakpoint bp); void insertBreakpoint(Breakpoint bp);
void removeBreakpoint(Breakpoint bp); void removeBreakpoint(Breakpoint bp);
void assignValueInDebugger(const WatchData *data, void assignValueInDebugger(WatchItem *item,
const QString &expr, const QVariant &value); const QString &expr, const QVariant &value);
void executeDebuggerCommand(const QString &command, DebuggerLanguages languages); void executeDebuggerCommand(const QString &command, DebuggerLanguages languages);
@@ -96,7 +96,7 @@ private:
bool supportsThreads() const { return true; } bool supportsThreads() const { return true; }
bool isSynchronous() const { return true; } bool isSynchronous() const { return true; }
void updateWatchData(const WatchData &data); void updateWatchItem(WatchItem *item);
QString mainPythonFile() const; QString mainPythonFile() const;
void runCommand(const DebuggerCommand &cmd); void runCommand(const DebuggerCommand &cmd);

View File

@@ -38,6 +38,7 @@ namespace Debugger {
namespace Internal { namespace Internal {
class WatchData; class WatchData;
class WatchItem;
class BreakHandler; class BreakHandler;
class BreakpointModelId; class BreakpointModelId;
class QmlEngine; class QmlEngine;

View File

@@ -112,18 +112,18 @@ bool QmlCppEngine::setToolTipExpression(const DebuggerToolTipContext &ctx)
return success; return success;
} }
void QmlCppEngine::updateWatchData(const WatchData &data) void QmlCppEngine::updateWatchItem(WatchItem *item)
{ {
if (data.isInspect()) if (item->isInspect())
m_qmlEngine->updateWatchData(data); m_qmlEngine->updateWatchItem(item);
else else
m_activeEngine->updateWatchData(data); m_activeEngine->updateWatchItem(item);
} }
void QmlCppEngine::watchDataSelected(const QByteArray &iname) void QmlCppEngine::watchDataSelected(const QByteArray &iname)
{ {
const WatchData *wd = watchHandler()->findData(iname); const WatchItem *item = watchHandler()->findItem(iname);
if (wd && wd->isInspect()) if (item && item->isInspect())
m_qmlEngine->watchDataSelected(iname); m_qmlEngine->watchDataSelected(iname);
} }
@@ -264,13 +264,13 @@ void QmlCppEngine::selectThread(ThreadId threadId)
m_activeEngine->selectThread(threadId); m_activeEngine->selectThread(threadId);
} }
void QmlCppEngine::assignValueInDebugger(const WatchData *data, void QmlCppEngine::assignValueInDebugger(WatchItem *item,
const QString &expr, const QVariant &value) const QString &expr, const QVariant &value)
{ {
if (data->isInspect()) if (item->isInspect())
m_qmlEngine->assignValueInDebugger(data, expr, value); m_qmlEngine->assignValueInDebugger(item, expr, value);
else else
m_activeEngine->assignValueInDebugger(data, expr, value); m_activeEngine->assignValueInDebugger(item, expr, value);
} }
void QmlCppEngine::notifyInferiorIll() void QmlCppEngine::notifyInferiorIll()

View File

@@ -48,7 +48,7 @@ public:
bool canDisplayTooltip() const; bool canDisplayTooltip() const;
bool setToolTipExpression(const DebuggerToolTipContext &); bool setToolTipExpression(const DebuggerToolTipContext &);
void updateWatchData(const WatchData &data); void updateWatchItem(WatchItem *item);
void watchDataSelected(const QByteArray &iname); void watchDataSelected(const QByteArray &iname);
void watchPoint(const QPoint &); void watchPoint(const QPoint &);
@@ -79,7 +79,7 @@ public:
bool acceptsBreakpoint(Breakpoint bp) const; bool acceptsBreakpoint(Breakpoint bp) const;
void selectThread(ThreadId threadId); void selectThread(ThreadId threadId);
void assignValueInDebugger(const WatchData *data, void assignValueInDebugger(WatchItem *item,
const QString &expr, const QVariant &value); const QString &expr, const QVariant &value);
DebuggerEngine *cppEngine() { return m_cppEngine; } DebuggerEngine *cppEngine() { return m_cppEngine; }

View File

@@ -988,45 +988,41 @@ bool QmlEngine::setToolTipExpression(const DebuggerToolTipContext &context)
// //
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void QmlEngine::assignValueInDebugger(const WatchData *data, void QmlEngine::assignValueInDebugger(WatchItem *item,
const QString &expression, const QVariant &valueV) const QString &expression, const QVariant &valueV)
{ {
if (!expression.isEmpty()) { if (!expression.isEmpty()) {
if (data->isInspect() && m_inspectorAdapter.agent()) if (item->isInspect() && m_inspectorAdapter.agent())
m_inspectorAdapter.agent()->assignValue(data, expression, valueV); m_inspectorAdapter.agent()->assignValue(item, expression, valueV);
else if (m_adapter.activeDebuggerClient()) else if (m_adapter.activeDebuggerClient())
m_adapter.activeDebuggerClient()->assignValueInDebugger(data, expression, valueV); m_adapter.activeDebuggerClient()->assignValueInDebugger(item, expression, valueV);
} }
} }
void QmlEngine::updateWatchData(const WatchData &data) void QmlEngine::updateWatchItem(WatchItem *item)
{ {
// qDebug() << "UPDATE WATCH DATA" << data.toString(); // qDebug() << "UPDATE WATCH DATA" << data.toString();
//showStatusMessage(tr("Stopped."), 5000); //showStatusMessage(tr("Stopped."), 5000);
if (data.isInspect()) { if (item->isInspect()) {
m_inspectorAdapter.agent()->updateWatchData(data); m_inspectorAdapter.agent()->updateWatchData(*item);
} else { } else {
if (!data.name.isEmpty() && m_adapter.activeDebuggerClient()) { if (!item->name.isEmpty() && m_adapter.activeDebuggerClient()) {
if (data.isValueNeeded()) if (item->isValueNeeded())
m_adapter.activeDebuggerClient()->updateWatchData(data); m_adapter.activeDebuggerClient()->updateWatchData(*item);
if (data.isChildrenNeeded() if (item->isChildrenNeeded() && watchHandler()->isExpandedIName(item->iname)) {
&& watchHandler()->isExpandedIName(data.iname)) { m_adapter.activeDebuggerClient()->expandObject(item->iname, item->id);
m_adapter.activeDebuggerClient()->expandObject(data.iname, data.id);
} }
} }
synchronizeWatchers(); synchronizeWatchers();
} }
if (!data.isSomethingNeeded())
watchHandler()->insertData(data);
} }
void QmlEngine::watchDataSelected(const QByteArray &iname) void QmlEngine::watchDataSelected(const QByteArray &iname)
{ {
const WatchData *wd = watchHandler()->findData(iname); const WatchItem *item = watchHandler()->findItem(iname);
if (wd && wd->isInspect()) if (item && item->isInspect())
m_inspectorAdapter.agent()->watchDataSelected(wd); m_inspectorAdapter.agent()->watchDataSelected(item->id);
} }
void QmlEngine::synchronizeWatchers() void QmlEngine::synchronizeWatchers()
@@ -1153,11 +1149,11 @@ void QmlEngine::updateCurrentContext()
context = stackHandler()->currentFrame().function; context = stackHandler()->currentFrame().function;
} else { } else {
QModelIndex currentIndex = inspectorTreeView()->currentIndex(); QModelIndex currentIndex = inspectorTreeView()->currentIndex();
const WatchData *currentData = watchHandler()->watchData(currentIndex); const WatchData *currentData = watchHandler()->watchItem(currentIndex);
if (!currentData) if (!currentData)
return; return;
const WatchData *parentData = watchHandler()->watchData(currentIndex.parent()); const WatchData *parentData = watchHandler()->watchItem(currentIndex.parent());
const WatchData *grandParentData = watchHandler()->watchData( const WatchData *grandParentData = watchHandler()->watchItem(
currentIndex.parent().parent()); currentIndex.parent().parent());
if (currentData->id != parentData->id) if (currentData->id != parentData->id)
context = currentData->name; context = currentData->name;
@@ -1217,7 +1213,7 @@ bool QmlEngine::evaluateScript(const QString &expression)
if (state() != InferiorStopOk) { if (state() != InferiorStopOk) {
QModelIndex currentIndex = inspectorTreeView()->currentIndex(); QModelIndex currentIndex = inspectorTreeView()->currentIndex();
QmlInspectorAgent *agent = m_inspectorAdapter.agent(); QmlInspectorAgent *agent = m_inspectorAdapter.agent();
quint32 queryId = agent->queryExpressionResult(watchHandler()->watchData(currentIndex)->id, quint32 queryId = agent->queryExpressionResult(watchHandler()->watchItem(currentIndex)->id,
expression); expression);
if (queryId) { if (queryId) {
queryIds << queryId; queryIds << queryId;

View File

@@ -145,10 +145,9 @@ private:
void changeBreakpoint(Breakpoint bp); void changeBreakpoint(Breakpoint bp);
bool acceptsBreakpoint(Breakpoint bp) const; bool acceptsBreakpoint(Breakpoint bp) const;
void assignValueInDebugger(const WatchData *data, void assignValueInDebugger(WatchItem *item,
const QString &expr, const QVariant &value); const QString &expr, const QVariant &value);
void loadSymbols(const QString &moduleName); void loadSymbols(const QString &moduleName);
void loadAllSymbols(); void loadAllSymbols();
void requestModuleSymbols(const QString &moduleName); void requestModuleSymbols(const QString &moduleName);
@@ -158,7 +157,7 @@ private:
void reloadFullStack() {} void reloadFullStack() {}
bool supportsThreads() const { return false; } bool supportsThreads() const { return false; }
void updateWatchData(const WatchData &data); void updateWatchItem(WatchItem *item);
void watchDataSelected(const QByteArray &iname); void watchDataSelected(const QByteArray &iname);
void executeDebuggerCommand(const QString &command, DebuggerLanguages languages); void executeDebuggerCommand(const QString &command, DebuggerLanguages languages);
bool evaluateScript(const QString &expression); bool evaluateScript(const QString &expression);

View File

@@ -125,13 +125,13 @@ void QmlInspectorAgent::updateWatchData(const WatchData &data)
} }
} }
void QmlInspectorAgent::watchDataSelected(const WatchData *data) void QmlInspectorAgent::watchDataSelected(quint64 id)
{ {
qCDebug(qmlInspectorLog) << __FUNCTION__ << '(' << data->id << ')'; qCDebug(qmlInspectorLog) << __FUNCTION__ << '(' << id << ')';
if (data->id) { if (id) {
QTC_ASSERT(m_debugIdLocations.keys().contains(data->id), return); QTC_ASSERT(m_debugIdLocations.keys().contains(id), return);
emit jumpToObjectDefinition(m_debugIdLocations.value(data->id), data->id); emit jumpToObjectDefinition(m_debugIdLocations.value(id), id);
} }
} }
@@ -154,7 +154,7 @@ bool QmlInspectorAgent::selectObjectInTree(int debugId)
using namespace QmlDebug::Constants; using namespace QmlDebug::Constants;
if (m_engineClient->objectName() == QLatin1String(QDECLARATIVE_ENGINE)) { if (m_engineClient->objectName() == QLatin1String(QDECLARATIVE_ENGINE)) {
// reset current Selection // reset current Selection
QByteArray root = m_debuggerEngine->watchHandler()->watchData(QModelIndex())->iname; QByteArray root = m_debuggerEngine->watchHandler()->watchItem(QModelIndex())->iname;
m_debuggerEngine->watchHandler()->setCurrentItem(root); m_debuggerEngine->watchHandler()->setCurrentItem(root);
} else { } else {
fetchObject(debugId); fetchObject(debugId);
@@ -256,8 +256,8 @@ ObjectReference QmlInspectorAgent::objectForName(
const WatchHandler *watchHandler = m_debuggerEngine->watchHandler(); const WatchHandler *watchHandler = m_debuggerEngine->watchHandler();
while (iter.hasNext()) { while (iter.hasNext()) {
iter.next(); iter.next();
const WatchData *wd = watchHandler->findData(iter.value()); const WatchItem *item = watchHandler->findItem(iter.value());
if (wd && wd->name == objectId) if (item && item->name == objectId)
return ObjectReference(iter.key()); return ObjectReference(iter.key());
} }
} }
@@ -313,13 +313,11 @@ QHash<int,QString> QmlInspectorAgent::rootObjectIds() const
{ {
QHash<int,QString> rIds; QHash<int,QString> rIds;
const WatchHandler *watchHandler = m_debuggerEngine->watchHandler(); const WatchHandler *watchHandler = m_debuggerEngine->watchHandler();
foreach (const QByteArray &in, m_debugIdToIname) { foreach (const QByteArray &iname, m_debugIdToIname) {
const WatchData *data = watchHandler->findData(in); if (const WatchItem *item = watchHandler->findItem(iname)) {
if (!data) int debugId = item->id;
continue; rIds.insert(debugId, QLatin1String(item->type));
int debugId = data->id; }
QString className = QLatin1String(data->type);
rIds.insert(debugId, className);
} }
return rIds; return rIds;
} }
@@ -415,10 +413,10 @@ QString QmlInspectorAgent::displayName(int objectDebugId) const
return QString(); return QString();
if (m_debugIdToIname.contains(objectDebugId)) { if (m_debugIdToIname.contains(objectDebugId)) {
const WatchData *data = m_debuggerEngine->watchHandler()->findData( const WatchItem *item = m_debuggerEngine->watchHandler()->findItem(
m_debugIdToIname.value(objectDebugId)); m_debugIdToIname.value(objectDebugId));
QTC_ASSERT(data, return QString()); QTC_ASSERT(item, return QString());
return data->name; return item->name;
} }
return QString(); return QString();
} }
@@ -505,14 +503,12 @@ void QmlInspectorAgent::onValueChanged(int debugId, const QByteArray &propertyNa
const QByteArray iname = m_debugIdToIname.value(debugId) + const QByteArray iname = m_debugIdToIname.value(debugId) +
".[properties]." + propertyName; ".[properties]." + propertyName;
WatchHandler *watchHandler = m_debuggerEngine->watchHandler(); WatchHandler *watchHandler = m_debuggerEngine->watchHandler();
const WatchData *data = watchHandler->findData(iname);
qCDebug(qmlInspectorLog) qCDebug(qmlInspectorLog)
<< __FUNCTION__ << '(' << debugId << ')' << iname << __FUNCTION__ << '(' << debugId << ')' << iname
<< value.toString(); << value.toString();
if (data) { if (WatchItem *item = watchHandler->findItem(iname)) {
WatchData d(*data); item->value = value.toString();
d.value = value.toString(); item->update();
watchHandler->insertData(d);
} }
} }
@@ -745,7 +741,6 @@ void QmlInspectorAgent::addWatchData(const ObjectReference &obj,
QByteArray objIname = buildIName(parentIname, objDebugId); QByteArray objIname = buildIName(parentIname, objDebugId);
if (append) { if (append) {
WatchData objWatch;
QString name = obj.idString(); QString name = obj.idString();
if (name.isEmpty()) if (name.isEmpty())
name = obj.className(); name = obj.className();
@@ -754,17 +749,16 @@ void QmlInspectorAgent::addWatchData(const ObjectReference &obj,
return; return;
// object // object
objWatch.id = objDebugId; auto objWatch = new WatchItem(objIname, name);
objWatch.exp = name.toLatin1(); objWatch->id = objDebugId;
objWatch.name = name; objWatch->exp = name.toLatin1();
objWatch.iname = objIname; objWatch->type = obj.className().toLatin1();
objWatch.type = obj.className().toLatin1(); objWatch->value = _("object");
objWatch.value = _("object"); objWatch->wantsChildren = true;
objWatch.setHasChildren(true); objWatch->setAllUnneeded();
objWatch.setAllUnneeded();
m_debuggerEngine->watchHandler()->insertData(objWatch); m_debuggerEngine->watchHandler()->insertItem(objWatch);
addObjectWatch(objWatch.id); addObjectWatch(objWatch->id);
if (m_debugIdToIname.contains(objDebugId)) { if (m_debugIdToIname.contains(objDebugId)) {
// The data needs to be removed since we now know the parent and // The data needs to be removed since we now know the parent and
// hence we can insert the data in the correct position // hence we can insert the data in the correct position
@@ -786,22 +780,22 @@ void QmlInspectorAgent::addWatchData(const ObjectReference &obj,
if (append && obj.properties().count()) { if (append && obj.properties().count()) {
QByteArray iname = objIname + ".[properties]"; QByteArray iname = objIname + ".[properties]";
auto propertiesWatch = new WatchItem(iname, tr("Properties")); auto propertiesWatch = new WatchItem(iname, tr("Properties"));
propertiesWatch->d.id = objDebugId; propertiesWatch->id = objDebugId;
propertiesWatch->d.value = _("list"); propertiesWatch->value = _("list");
propertiesWatch->d.setHasChildren(true); propertiesWatch->wantsChildren = true;
propertiesWatch->d.setAllUnneeded(); propertiesWatch->setAllUnneeded();
foreach (const PropertyReference &property, obj.properties()) { foreach (const PropertyReference &property, obj.properties()) {
const QString propertyName = property.name(); const QString propertyName = property.name();
if (propertyName.isEmpty()) if (propertyName.isEmpty())
continue; continue;
auto propertyWatch = new WatchItem(buildIName(iname, propertyName), propertyName); auto propertyWatch = new WatchItem(buildIName(iname, propertyName), propertyName);
propertyWatch->d.id = objDebugId; propertyWatch->id = objDebugId;
propertyWatch->d.exp = propertyName.toLatin1(); propertyWatch->exp = propertyName.toLatin1();
propertyWatch->d.type = property.valueTypeName().toLatin1(); propertyWatch->type = property.valueTypeName().toLatin1();
propertyWatch->d.value = property.value().toString(); propertyWatch->value = property.value().toString();
propertyWatch->d.setAllUnneeded(); propertyWatch->wantsChildren = false;
propertyWatch->d.setHasChildren(false); propertyWatch->setAllUnneeded();
propertiesWatch->appendChild(propertyWatch); propertiesWatch->appendChild(propertyWatch);
} }

View File

@@ -57,7 +57,7 @@ public:
void assignValue(const WatchData *data, const QString &expression, const QVariant &valueV); void assignValue(const WatchData *data, const QString &expression, const QVariant &valueV);
void updateWatchData(const WatchData &data); void updateWatchData(const WatchData &data);
void watchDataSelected(const WatchData *data); void watchDataSelected(quint64 id);
bool selectObjectInTree(int debugId); bool selectObjectInTree(int debugId);
quint32 setBindingForObject(int objectDebugId, quint32 setBindingForObject(int objectDebugId,

View File

@@ -253,7 +253,7 @@ void QmlV8DebuggerClientPrivate::evaluate(const QString expr, bool global,
QScriptValue ctxtList = parser.call(QScriptValue(), QScriptValueList() << _(ARRAY )); QScriptValue ctxtList = parser.call(QScriptValue(), QScriptValueList() << _(ARRAY ));
while (rowCount) { while (rowCount) {
QModelIndex index = watchModel->index(--rowCount, 0); QModelIndex index = watchModel->index(--rowCount, 0);
const WatchData *data = watchHandler->watchData(index); const WatchData *data = watchHandler->watchItem(index);
QScriptValue ctxt = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT))); QScriptValue ctxt = parser.call(QScriptValue(), QScriptValueList() << QScriptValue(_(OBJECT)));
ctxt.setProperty(_(NAME), QScriptValue(data->name)); ctxt.setProperty(_(NAME), QScriptValue(data->name));
ctxt.setProperty(_(HANDLE), QScriptValue(int(data->id))); ctxt.setProperty(_(HANDLE), QScriptValue(int(data->id)));
@@ -969,7 +969,7 @@ void QmlV8DebuggerClient::expandObject(const QByteArray &iname, quint64 objectId
{ {
if (objectId == 0) { if (objectId == 0) {
//We may have got the global object //We may have got the global object
const WatchData *watch = d->engine->watchHandler()->findData(iname); const WatchItem *watch = d->engine->watchHandler()->findItem(iname);
if (watch->value == QLatin1String("global")) { if (watch->value == QLatin1String("global")) {
StackHandler *stackHandler = d->engine->stackHandler(); StackHandler *stackHandler = d->engine->stackHandler();
if (stackHandler->isContentsValid() && stackHandler->currentFrame().isUsable()) { if (stackHandler->isContentsValid() && stackHandler->currentFrame().isUsable()) {
@@ -1469,10 +1469,9 @@ void QmlV8DebuggerClient::setCurrentFrameDetails(const QVariant &bodyVal, const
QHash<quint64, QByteArray> handlesToLookup; QHash<quint64, QByteArray> handlesToLookup;
// Store handles of all expanded watch data // Store handles of all expanded watch data
foreach (const QByteArray &iname, expandedInames) { foreach (const QByteArray &iname, expandedInames) {
const WatchData *wd = watchHandler->findData(iname); const WatchItem *item = watchHandler->findItem(iname);
if (!wd || !wd->isLocal()) if (item && item->isLocal())
continue; handlesToLookup.insert(item->id, iname);
handlesToLookup.insert(wd->id, iname);
} }
watchHandler->removeAllData(); watchHandler->removeAllData();
if (frameIndex < 0) if (frameIndex < 0)
@@ -1483,22 +1482,19 @@ void QmlV8DebuggerClient::setCurrentFrameDetails(const QVariant &bodyVal, const
//Set "this" variable //Set "this" variable
{ {
WatchData data; auto item = new WatchItem("local.this", QLatin1String("this"));
data.exp = QByteArray("this");
data.name = QLatin1String(data.exp);
data.iname = QByteArray("local.") + data.exp;
QmlV8ObjectData objectData = extractData(currentFrame.value(_("receiver")), refsVal); QmlV8ObjectData objectData = extractData(currentFrame.value(_("receiver")), refsVal);
data.id = objectData.handle; item->id = objectData.handle;
data.type = objectData.type; item->type = objectData.type;
data.value = objectData.value.toString(); item->value = objectData.value.toString();
data.setHasChildren(objectData.properties.count()); item->setHasChildren(objectData.properties.count());
//Incase of global object, we do not get children //Incase of global object, we do not get children
//Set children nevertheless and query later //Set children nevertheless and query later
if (data.value == QLatin1String("global")) { if (item->value == QLatin1String("global")) {
data.setHasChildren(true); item->setHasChildren(true);
data.id = 0; item->id = 0;
} }
watchHandler->insertData(data); watchHandler->insertItem(item);
} }
const QVariantList currentFrameScopes = currentFrame.value(_("scopes")).toList(); const QVariantList currentFrameScopes = currentFrame.value(_("scopes")).toList();
@@ -1555,25 +1551,25 @@ void QmlV8DebuggerClient::updateScope(const QVariant &bodyVal, const QVariant &r
QList<int> handlesToLookup; QList<int> handlesToLookup;
foreach (const QVariant &property, objectData.properties) { foreach (const QVariant &property, objectData.properties) {
QmlV8ObjectData localData = extractData(property, refsVal); QmlV8ObjectData localData = extractData(property, refsVal);
WatchData data; auto item = new WatchItem;
data.exp = localData.name; item->exp = localData.name;
//Check for v8 specific local data //Check for v8 specific local data
if (data.exp.startsWith('.') || data.exp.isEmpty()) if (item->exp.startsWith('.') || item->exp.isEmpty())
continue; continue;
data.name = QLatin1String(data.exp); item->name = QLatin1String(item->exp);
data.iname = QByteArray("local.") + data.exp; item->iname = QByteArray("local.") + item->exp;
int handle = localData.handle; int handle = localData.handle;
if (localData.value.isValid()) { if (localData.value.isValid()) {
data.id = handle; item->id = handle;
data.type = localData.type; item->type = localData.type;
data.value = localData.value.toString(); item->value = localData.value.toString();
data.setHasChildren(localData.properties.count()); item->setHasChildren(localData.properties.count());
d->engine->watchHandler()->insertData(data); d->engine->watchHandler()->insertItem(item);
} else { } else {
handlesToLookup << handle; handlesToLookup << handle;
d->localsAndWatchers.insertMulti(handle, data.exp); d->localsAndWatchers.insertMulti(handle, item->exp);
} }
} }
@@ -1636,7 +1632,7 @@ void QmlV8DebuggerClient::updateEvaluationResult(int sequence, bool success,
d->scope(index); d->scope(index);
//Also update "this" //Also update "this"
QByteArray iname("local.this"); QByteArray iname("local.this");
const WatchData *parent = watchHandler->findData(iname); const WatchItem *parent = watchHandler->findItem(iname);
d->localsAndWatchers.insertMulti(parent->id, iname); d->localsAndWatchers.insertMulti(parent->id, iname);
d->lookup(QList<int>() << parent->id); d->lookup(QList<int>() << parent->id);
@@ -1658,29 +1654,27 @@ void QmlV8DebuggerClient::updateEvaluationResult(int sequence, bool success,
QmlV8ObjectData body = extractData(bodyVal, refsVal); QmlV8ObjectData body = extractData(bodyVal, refsVal);
if (d->evaluatingExpression.contains(sequence)) { if (d->evaluatingExpression.contains(sequence)) {
QString exp = d->evaluatingExpression.take(sequence); QString exp = d->evaluatingExpression.take(sequence);
WatchData data;
//Do we have request to evaluate a local? //Do we have request to evaluate a local?
if (exp.startsWith(QLatin1String("local."))) { if (exp.startsWith(QLatin1String("local."))) {
const WatchData *watch = watchHandler->findData(exp.toLatin1()); const WatchItem *item = watchHandler->findItem(exp.toLatin1());
createWatchDataList(watch, body.properties, refsVal); createWatchDataList(item, body.properties, refsVal);
} else { } else {
QByteArray iname = watchHandler->watcherName(exp.toLatin1()); QByteArray iname = watchHandler->watcherName(exp.toLatin1());
SDEBUG(QString(iname)); SDEBUG(QString(iname));
data.exp = exp.toLatin1(); auto item = new WatchItem(iname, exp);
data.name = exp; item->exp = exp.toLatin1();
data.iname = iname; item->id = body.handle;
data.id = body.handle;
if (success) { if (success) {
data.type = body.type; item->type = body.type;
data.value = body.value.toString(); item->value = body.value.toString();
data.hasChildren = body.properties.count(); item->wantsChildren = body.properties.count();
} else { } else {
//Do not set type since it is unknown //Do not set type since it is unknown
data.setError(body.value.toString()); item->setError(body.value.toString());
} }
watchHandler->insertData(data); watchHandler->insertItem(item);
createWatchDataList(&data, body.properties, refsVal); createWatchDataList(item, body.properties, refsVal);
} }
//Insert the newly evaluated expression to the Watchers Window //Insert the newly evaluated expression to the Watchers Window
} }
@@ -1709,27 +1703,27 @@ void QmlV8DebuggerClient::expandLocalsAndWatchers(const QVariant &bodyVal, const
if (prepend.startsWith("local.") || prepend.startsWith("watch.")) { if (prepend.startsWith("local.") || prepend.startsWith("watch.")) {
// Data for expanded local/watch. // Data for expanded local/watch.
// Could be an object or function. // Could be an object or function.
const WatchData *parent = watchHandler->findData(prepend); const WatchItem *parent = watchHandler->findItem(prepend);
createWatchDataList(parent, bodyObjectData.properties, refsVal); createWatchDataList(parent, bodyObjectData.properties, refsVal);
} else { } else {
//rest //rest
WatchData data; auto item = new WatchItem;
data.exp = prepend; item->exp = prepend;
data.name = QLatin1String(data.exp); item->name = QLatin1String(item->exp);
data.iname = QByteArray("local.") + data.exp; item->iname = QByteArray("local.") + item->exp;
data.id = handle.toInt(); item->id = handle.toInt();
data.type = bodyObjectData.type; item->type = bodyObjectData.type;
data.value = bodyObjectData.value.toString(); item->value = bodyObjectData.value.toString();
data.setHasChildren(bodyObjectData.properties.count()); item->setHasChildren(bodyObjectData.properties.count());
d->engine->watchHandler()->insertData(data); d->engine->watchHandler()->insertItem(item);
} }
} }
} }
void QmlV8DebuggerClient::createWatchDataList(const WatchData *parent, void QmlV8DebuggerClient::createWatchDataList(const WatchItem *parent,
const QVariantList &properties, const QVariantList &properties,
const QVariant &refsVal) const QVariant &refsVal)
{ {
@@ -1737,27 +1731,27 @@ void QmlV8DebuggerClient::createWatchDataList(const WatchData *parent,
QTC_ASSERT(parent, return); QTC_ASSERT(parent, return);
foreach (const QVariant &property, properties) { foreach (const QVariant &property, properties) {
QmlV8ObjectData propertyData = extractData(property, refsVal); QmlV8ObjectData propertyData = extractData(property, refsVal);
WatchData data; auto item = new WatchItem;
data.name = QString::fromUtf8(propertyData.name); item->name = QString::fromUtf8(propertyData.name);
//Check for v8 specific local data //Check for v8 specific local data
if (data.name.startsWith(QLatin1Char('.')) || data.name.isEmpty()) if (item->name.startsWith(QLatin1Char('.')) || item->name.isEmpty())
continue; continue;
if (parent->type == "object") { if (parent->type == "object") {
if (parent->value == _("Array")) if (parent->value == _("Array"))
data.exp = parent->exp + '[' + data.name.toLatin1() + ']'; item->exp = parent->exp + '[' + item->name.toLatin1() + ']';
else if (parent->value == _("Object")) else if (parent->value == _("Object"))
data.exp = parent->exp + '.' + data.name.toLatin1(); item->exp = parent->exp + '.' + item->name.toLatin1();
} else { } else {
data.exp = data.name.toLatin1(); item->exp = item->name.toLatin1();
} }
data.iname = parent->iname + '.' + data.name.toLatin1(); item->iname = parent->iname + '.' + item->name.toLatin1();
data.id = propertyData.handle; item->id = propertyData.handle;
data.type = propertyData.type; item->type = propertyData.type;
data.value = propertyData.value.toString(); item->value = propertyData.value.toString();
data.setHasChildren(propertyData.properties.count()); item->setHasChildren(propertyData.properties.count());
d->engine->watchHandler()->insertData(data); d->engine->watchHandler()->insertItem(item);
} }
} }
} }

View File

@@ -111,7 +111,7 @@ private:
void updateEvaluationResult(int sequence, bool success, const QVariant &bodyVal, void updateEvaluationResult(int sequence, bool success, const QVariant &bodyVal,
const QVariant &refsVal); const QVariant &refsVal);
void expandLocalsAndWatchers(const QVariant &bodyVal, const QVariant &refsVal); void expandLocalsAndWatchers(const QVariant &bodyVal, const QVariant &refsVal);
void createWatchDataList(const WatchData *parent, void createWatchDataList(const WatchItem *parent,
const QVariantList &properties, const QVariantList &properties,
const QVariant &refsVal); const QVariant &refsVal);

View File

@@ -482,16 +482,18 @@ void QScriptDebuggerClient::messageReceived(const QByteArray &data)
d->logReceiveMessage(QLatin1String(command) + QLatin1Char(' ') d->logReceiveMessage(QLatin1String(command) + QLatin1Char(' ')
+ QLatin1String(iname) + QLatin1Char(' ') + data.value); + QLatin1String(iname) + QLatin1Char(' ') + data.value);
data.iname = iname;
auto item = new WatchItem(data);
item->iname = iname;
if (iname.startsWith("watch.")) { if (iname.startsWith("watch.")) {
watchHandler->insertData(data); watchHandler->insertItem(item);
} else if (iname == "console") { } else if (iname == "console") {
d->engine->showMessage(data.value, ConsoleOutput); d->engine->showMessage(item->value, ConsoleOutput);
} else if (iname.startsWith("local.")) { } else if (iname.startsWith("local.")) {
data.name = data.name.left(data.name.indexOf(QLatin1Char(' '))); item->name = item->name.left(item->name.indexOf(QLatin1Char(' ')));
watchHandler->insertData(data); watchHandler->insertItem(item);
} else { } else {
qWarning() << "QmlEngine: Unexcpected result: " << iname << data.value; qWarning() << "QmlEngine: Unexcpected result: " << iname << item->value;
} }
} else if (command == "EXPANDED") { } else if (command == "EXPANDED") {
QList<WatchData> result; QList<WatchData> result;
@@ -504,7 +506,7 @@ void QScriptDebuggerClient::messageReceived(const QByteArray &data)
foreach (WatchData data, result) { foreach (WatchData data, result) {
data.iname = iname + '.' + data.exp; data.iname = iname + '.' + data.exp;
watchHandler->insertData(data); watchHandler->insertItem(new WatchItem(data));
if (watchHandler->isExpandedIName(data.iname) && qint64(data.id) != -1) { if (watchHandler->isExpandedIName(data.iname) && qint64(data.id) != -1) {
needPing = true; needPing = true;
@@ -552,9 +554,10 @@ void QScriptDebuggerClient::insertLocalsAndWatches(QList<WatchData> &locals,
return; return;
bool needPing = false; bool needPing = false;
foreach (WatchData data, watches) { foreach (const WatchData &data, watches) {
data.iname = watchHandler->watcherName(data.exp); auto item = new WatchItem(data);
watchHandler->insertData(data); item->iname = watchHandler->watcherName(data.exp);
watchHandler->insertItem(item);
if (watchHandler->isExpandedIName(data.iname) && qint64(data.id) != -1) { if (watchHandler->isExpandedIName(data.iname) && qint64(data.id) != -1) {
needPing = true; needPing = true;
@@ -562,11 +565,12 @@ void QScriptDebuggerClient::insertLocalsAndWatches(QList<WatchData> &locals,
} }
} }
foreach (WatchData data, locals) { foreach (const WatchData &data, locals) {
if (data.name == QLatin1String("<no initialized data>")) auto item = new WatchItem(data);
data.name = tr("No Local Variables"); if (item->name == QLatin1String("<no initialized data>"))
data.iname = "local." + data.exp; item->name = tr("No Local Variables");
watchHandler->insertData(data); item->iname = "local." + item->exp;
watchHandler->insertItem(item);
if (watchHandler->isExpandedIName(data.iname) && qint64(data.id) != -1) { if (watchHandler->isExpandedIName(data.iname) && qint64(data.id) != -1) {
needPing = true; needPing = true;

View File

@@ -128,7 +128,7 @@ WatchData::WatchData() :
bitpos(0), bitpos(0),
bitsize(0), bitsize(0),
elided(0), elided(0),
hasChildren(false), wantsChildren(false),
valueEnabled(true), valueEnabled(true),
valueEditable(true), valueEditable(true),
error(false), error(false),
@@ -150,7 +150,7 @@ bool WatchData::isEqual(const WatchData &other) const
&& address == other.address && address == other.address
&& size == other.size && size == other.size
&& elided == other.elided && elided == other.elided
&& hasChildren == other.hasChildren && wantsChildren == other.wantsChildren
&& valueEnabled == other.valueEnabled && valueEnabled == other.valueEnabled
&& valueEditable == other.valueEditable && valueEditable == other.valueEditable
&& error == other.error; && error == other.error;
@@ -177,7 +177,7 @@ void WatchData::setError(const QString &msg)
{ {
setAllUnneeded(); setAllUnneeded();
value = msg; value = msg;
setHasChildren(false); wantsChildren = false;
valueEnabled = false; valueEnabled = false;
valueEditable = false; valueEditable = false;
error = true; error = true;
@@ -188,7 +188,7 @@ void WatchData::setValue(const QString &value0)
value = value0; value = value0;
if (value == QLatin1String("{...}")) { if (value == QLatin1String("{...}")) {
value.clear(); value.clear();
hasChildren = true; // at least one... wantsChildren = true; // at least one...
} }
// strip off quoted characters for chars. // strip off quoted characters for chars.
if (value.endsWith(QLatin1Char('\'')) && type.endsWith("char")) { if (value.endsWith(QLatin1Char('\'')) && type.endsWith("char")) {
@@ -334,7 +334,7 @@ QString WatchData::toString() const
str << "type=\"" << type << doubleQuoteComma; str << "type=\"" << type << doubleQuoteComma;
str << "hasChildren=\"" << (hasChildren ? "true" : "false") << doubleQuoteComma; str << "wantsChildren=\"" << (wantsChildren ? "true" : "false") << doubleQuoteComma;
if (isChildrenNeeded()) if (isChildrenNeeded())
str << "children=<needed>,"; str << "children=<needed>,";
@@ -604,10 +604,6 @@ void parseChildrenData(const WatchData &data0, const GdbMi &item,
mi = item["editformat"]; mi = item["editformat"];
data.editformat = mi.toInt(); data.editformat = mi.toInt();
mi = item["typeformats"];
if (mi.isValid())
data.typeFormats = QString::fromUtf8(mi.data());
mi = item["valueelided"]; mi = item["valueelided"];
if (mi.isValid()) if (mi.isValid())
data.elided = mi.toInt(); data.elided = mi.toInt();

View File

@@ -72,7 +72,7 @@ public:
bool isChildrenNeeded() const { return state & ChildrenNeeded; } bool isChildrenNeeded() const { return state & ChildrenNeeded; }
void setChildrenNeeded() { state = State(state | ChildrenNeeded); } void setChildrenNeeded() { state = State(state | ChildrenNeeded); }
void setChildrenUnneeded() { state = State(state & ~ChildrenNeeded); } void setChildrenUnneeded() { state = State(state & ~ChildrenNeeded); }
void setHasChildren(bool c) { hasChildren = c; if (!c) setChildrenUnneeded(); } void setHasChildren(bool c) { wantsChildren = c; if (!c) setChildrenUnneeded(); }
bool isLocal() const { return iname.startsWith("local."); } bool isLocal() const { return iname.startsWith("local."); }
bool isWatcher() const { return iname.startsWith("watch."); } bool isWatcher() const { return iname.startsWith("watch."); }
@@ -113,7 +113,6 @@ public:
QString value; // Displayed value QString value; // Displayed value
QByteArray editvalue; // Displayed value QByteArray editvalue; // Displayed value
qint32 editformat; // Format of displayed value qint32 editformat; // Format of displayed value
QString typeFormats; // Selection of formats of displayed value
QByteArray type; // Type for further processing QByteArray type; // Type for further processing
QString displayedType;// Displayed type (optional) QString displayedType;// Displayed type (optional)
quint64 address; // Displayed address of the actual object quint64 address; // Displayed address of the actual object
@@ -122,7 +121,7 @@ public:
uint bitpos; // Position within bit fields uint bitpos; // Position within bit fields
uint bitsize; // Size in case of bit fields uint bitsize; // Size in case of bit fields
int elided; // Full size if value was cut off, -1 if cut on unknown size, 0 otherwise int elided; // Full size if value was cut off, -1 if cut on unknown size, 0 otherwise
bool hasChildren; bool wantsChildren;
bool valueEnabled; // Value will be enabled or not bool valueEnabled; // Value will be enabled or not
bool valueEditable; // Value will be editable bool valueEditable; // Value will be editable
bool error; bool error;

View File

@@ -110,8 +110,6 @@ static QByteArray stripForFormat(const QByteArray &ba)
class SeparatedView : public QTabWidget class SeparatedView : public QTabWidget
{ {
Q_OBJECT
public: public:
SeparatedView() : QTabWidget(Internal::mainWindow()) SeparatedView() : QTabWidget(Internal::mainWindow())
{ {
@@ -199,26 +197,27 @@ public:
explicit WatchModel(WatchHandler *handler); explicit WatchModel(WatchHandler *handler);
static QString nameForFormat(int format); static QString nameForFormat(int format);
TypeFormatList typeFormatList(const WatchData &value) const;
QVariant data(const QModelIndex &idx, int role) const; QVariant data(const QModelIndex &idx, int role) const;
bool setData(const QModelIndex &idx, const QVariant &value, int role); bool setData(const QModelIndex &idx, const QVariant &value, int role);
void insertDataItem(const WatchData &data);
void reinsertAllData(); void reinsertAllData();
void reinsertAllDataHelper(WatchItem *item, QList<WatchData> *data); void reinsertAllDataHelper(WatchItem *item, QList<WatchData> *data);
QString displayForAutoTest(const QByteArray &iname) const; QString displayForAutoTest(const QByteArray &iname) const;
void reinitialize(bool includeInspectData = false); void reinitialize(bool includeInspectData = false);
friend QDebug operator<<(QDebug d, const WatchModel &m); WatchItem *findItem(const QByteArray &iname) const;
void insertItem(WatchItem *item);
void reexpandItems();
void showInEditorHelper(QString *contents, WatchItem *item, int level);
void setCurrentItem(const QByteArray &iname); void setCurrentItem(const QByteArray &iname);
void showEditValue(const WatchData &data);
QString removeNamespaces(QString str) const; QString removeNamespaces(QString str) const;
DebuggerEngine *engine() const; DebuggerEngine *engine() const;
bool contentIsValid() const; bool contentIsValid() const;
public:
WatchHandler *m_handler; // Not owned. WatchHandler *m_handler; // Not owned.
WatchItem *root() const { return static_cast<WatchItem *>(rootItem()); } WatchItem *root() const { return static_cast<WatchItem *>(rootItem()); }
@@ -228,21 +227,13 @@ public:
WatchItem *m_returnRoot; // Not owned. WatchItem *m_returnRoot; // Not owned.
WatchItem *m_tooltipRoot; // Not owned. WatchItem *m_tooltipRoot; // Not owned.
SeparatedView m_separatedView;
QSet<QByteArray> m_expandedINames; QSet<QByteArray> m_expandedINames;
QTimer m_requestUpdateTimer; QTimer m_requestUpdateTimer;
TypeFormatList builtinTypeFormatList(const WatchData &data) const;
QStringList dumperTypeFormatList(const WatchData &data) const;
DumperTypeFormats m_reportedTypeFormats; DumperTypeFormats m_reportedTypeFormats;
QHash<QByteArray, QString> m_valueCache;
WatchItem *createItem(const QByteArray &iname);
WatchItem *findItem(const QByteArray &iname) const;
friend class WatchItem;
typedef QHash<QByteArray, QString> ValueCache;
ValueCache m_valueCache;
void insertItem(WatchItem *item);
void reexpandItems();
}; };
WatchModel::WatchModel(WatchHandler *handler) WatchModel::WatchModel(WatchHandler *handler)
@@ -293,31 +284,21 @@ WatchItem *WatchModel::findItem(const QByteArray &iname) const
WatchItem *WatchItem::findItem(const QByteArray &iname) WatchItem *WatchItem::findItem(const QByteArray &iname)
{ {
if (d.iname == iname) if (this->iname == iname)
return this; return this;
foreach (TreeItem *child, children()) { foreach (TreeItem *child, children()) {
auto witem = static_cast<WatchItem *>(child); auto witem = static_cast<WatchItem *>(child);
if (witem->d.iname == iname) if (witem->iname == iname)
return witem; return witem;
if (witem->d.isAncestorOf(iname)) if (witem->isAncestorOf(iname))
return witem->findItem(iname); return witem->findItem(iname);
} }
return 0; return 0;
} }
void WatchModel::reinsertAllData()
{
QList<WatchData> list;
foreach (TreeItem *child, rootItem()->children())
reinsertAllDataHelper(static_cast<WatchItem *>(child), &list);
reinitialize(true);
for (int i = 0, n = list.size(); i != n; ++i)
insertDataItem(list.at(i));
}
void WatchModel::reinsertAllDataHelper(WatchItem *item, QList<WatchData> *data) void WatchModel::reinsertAllDataHelper(WatchItem *item, QList<WatchData> *data)
{ {
data->append(item->d); data->append(*item); // Slices intentionally.
data->back().setAllUnneeded(); data->back().setAllUnneeded();
foreach (TreeItem *child, item->children()) foreach (TreeItem *child, item->children())
reinsertAllDataHelper(static_cast<WatchItem *>(child), data); reinsertAllDataHelper(static_cast<WatchItem *>(child), data);
@@ -498,64 +479,63 @@ static QString translate(const QString &str)
QString WatchItem::formattedValue() const QString WatchItem::formattedValue() const
{ {
if (d.type == "bool") { if (type == "bool") {
if (d.value == QLatin1String("0")) if (value == QLatin1String("0"))
return QLatin1String("false"); return QLatin1String("false");
if (d.value == QLatin1String("1")) if (value == QLatin1String("1"))
return QLatin1String("true"); return QLatin1String("true");
return d.value; return value;
} }
const int format = itemFormat(); const int format = itemFormat();
// Append quoted, printable character also for decimal. // Append quoted, printable character also for decimal.
if (d.type.endsWith("char") || d.type.endsWith("QChar")) { if (type.endsWith("char") || type.endsWith("QChar")) {
bool ok; bool ok;
const int code = d.value.toInt(&ok); const int code = value.toInt(&ok);
return ok ? reformatCharacter(code, format) : d.value; return ok ? reformatCharacter(code, format) : value;
} }
if (format == HexadecimalIntegerFormat if (format == HexadecimalIntegerFormat
|| format == DecimalIntegerFormat || format == DecimalIntegerFormat
|| format == OctalIntegerFormat || format == OctalIntegerFormat
|| format == BinaryIntegerFormat) { || format == BinaryIntegerFormat) {
bool isSigned = d.value.startsWith(QLatin1Char('-')); bool isSigned = value.startsWith(QLatin1Char('-'));
quint64 raw = isSigned ? quint64(d.value.toLongLong()) : d.value.toULongLong(); quint64 raw = isSigned ? quint64(value.toLongLong()) : value.toULongLong();
return reformatInteger(raw, format, d.size, isSigned); return reformatInteger(raw, format, size, isSigned);
} }
if (format == ScientificFloatFormat) { if (format == ScientificFloatFormat) {
double dd = d.value.toDouble(); double dd = value.toDouble();
return QString::number(dd, 'e'); return QString::number(dd, 'e');
} }
if (format == CompactFloatFormat) { if (format == CompactFloatFormat) {
double dd = d.value.toDouble(); double dd = value.toDouble();
return QString::number(dd, 'g'); return QString::number(dd, 'g');
} }
if (d.type == "va_list") if (type == "va_list")
return d.value; return value;
if (!isPointerType(d.type) && !d.isVTablePointer()) { if (!isPointerType(type) && !isVTablePointer()) {
bool ok = false; bool ok = false;
qulonglong integer = d.value.toULongLong(&ok, 0); qulonglong integer = value.toULongLong(&ok, 0);
if (ok) { if (ok) {
const int format = itemFormat(); const int format = itemFormat();
return reformatInteger(integer, format, d.size, false); return reformatInteger(integer, format, size, false);
} }
} }
if (d.elided) { if (elided) {
QString v = d.value; QString v = value;
v.chop(1); v.chop(1);
v = translate(v); v = translate(v);
QString len = d.elided > 0 ? QString::number(d.elided) QString len = elided > 0 ? QString::number(elided) : QLatin1String("unknown length");
: QLatin1String("unknown length");
return v + QLatin1String("\"... (") + len + QLatin1Char(')'); return v + QLatin1String("\"... (") + len + QLatin1Char(')');
} }
return translate(d.value); return translate(value);
} }
// Get a pointer address from pointer values reported by the debugger. // Get a pointer address from pointer values reported by the debugger.
@@ -573,14 +553,14 @@ static inline quint64 pointerValue(QString data)
// Return the type used for editing // Return the type used for editing
int WatchItem::editType() const int WatchItem::editType() const
{ {
if (d.type == "bool") if (type == "bool")
return QVariant::Bool; return QVariant::Bool;
if (isIntType(d.type)) if (isIntType(type))
return d.type.contains('u') ? QVariant::ULongLong : QVariant::LongLong; return type.contains('u') ? QVariant::ULongLong : QVariant::LongLong;
if (isFloatType(d.type)) if (isFloatType(type))
return QVariant::Double; return QVariant::Double;
// Check for pointers using hex values (0xAD00 "Hallo") // Check for pointers using hex values (0xAD00 "Hallo")
if (isPointerType(d.type) && d.value.startsWith(QLatin1String("0x"))) if (isPointerType(type) && value.startsWith(QLatin1String("0x")))
return QVariant::ULongLong; return QVariant::ULongLong;
return QVariant::String; return QVariant::String;
} }
@@ -590,21 +570,21 @@ QVariant WatchItem::editValue() const
{ {
switch (editType()) { switch (editType()) {
case QVariant::Bool: case QVariant::Bool:
return d.value != QLatin1String("0") && d.value != QLatin1String("false"); return value != QLatin1String("0") && value != QLatin1String("false");
case QVariant::ULongLong: case QVariant::ULongLong:
if (isPointerType(d.type)) // Fix pointer values (0xAD00 "Hallo" -> 0xAD00) if (isPointerType(type)) // Fix pointer values (0xAD00 "Hallo" -> 0xAD00)
return QVariant(pointerValue(d.value)); return QVariant(pointerValue(value));
return QVariant(d.value.toULongLong()); return QVariant(value.toULongLong());
case QVariant::LongLong: case QVariant::LongLong:
return QVariant(d.value.toLongLong()); return QVariant(value.toLongLong());
case QVariant::Double: case QVariant::Double:
return QVariant(d.value.toDouble()); return QVariant(value.toDouble());
default: default:
break; break;
} }
// Some string value: '0x434 "Hallo"': // Some string value: '0x434 "Hallo"':
// Remove quotes and replace newlines, which will cause line edit troubles. // Remove quotes and replace newlines, which will cause line edit troubles.
QString stringValue = d.value; QString stringValue = value;
if (stringValue.endsWith(QLatin1Char('"'))) { if (stringValue.endsWith(QLatin1Char('"'))) {
const int leadingDoubleQuote = stringValue.indexOf(QLatin1Char('"')); const int leadingDoubleQuote = stringValue.indexOf(QLatin1Char('"'));
if (leadingDoubleQuote != stringValue.size() - 1) { if (leadingDoubleQuote != stringValue.size() - 1) {
@@ -618,11 +598,11 @@ QVariant WatchItem::editValue() const
bool WatchItem::canFetchMore() const bool WatchItem::canFetchMore() const
{ {
if (!d.hasChildren) if (!wantsChildren)
return false; return false;
if (!watchModel()) if (!watchModel())
return false; return false;
if (!watchModel()->contentIsValid() && !d.isInspect()) if (!watchModel()->contentIsValid() && !isInspect())
return false; return false;
return !fetchTriggered; return !fetchTriggered;
} }
@@ -632,11 +612,11 @@ void WatchItem::fetchMore()
if (fetchTriggered) if (fetchTriggered)
return; return;
watchModel()->m_expandedINames.insert(d.iname); watchModel()->m_expandedINames.insert(iname);
fetchTriggered = true; fetchTriggered = true;
if (children().isEmpty()) { if (children().isEmpty()) {
d.setChildrenNeeded(); setChildrenNeeded();
watchModel()->engine()->updateWatchData(d); watchModel()->engine()->updateWatchItem(this);
} }
} }
@@ -654,10 +634,10 @@ static QString truncateValue(QString v)
int WatchItem::itemFormat() const int WatchItem::itemFormat() const
{ {
const int individualFormat = theIndividualFormats.value(d.iname, AutomaticFormat); const int individualFormat = theIndividualFormats.value(iname, AutomaticFormat);
if (individualFormat != AutomaticFormat) if (individualFormat != AutomaticFormat)
return individualFormat; return individualFormat;
return theTypeFormats.value(stripForFormat(d.type), AutomaticFormat); return theTypeFormats.value(stripForFormat(type), AutomaticFormat);
} }
bool WatchModel::contentIsValid() const bool WatchModel::contentIsValid() const
@@ -671,17 +651,17 @@ bool WatchModel::contentIsValid() const
QString WatchItem::expression() const QString WatchItem::expression() const
{ {
if (!d.exp.isEmpty()) if (!exp.isEmpty())
return QString::fromLatin1(d.exp); return QString::fromLatin1(exp);
if (d.address && !d.type.isEmpty()) { if (address && !type.isEmpty()) {
return QString::fromLatin1("*(%1*)%2"). return QString::fromLatin1("*(%1*)%2").
arg(QLatin1String(d.type), QLatin1String(d.hexAddress())); arg(QLatin1String(type), QLatin1String(hexAddress()));
} }
if (const WatchItem *p = parentItem()) { if (const WatchItem *p = parentItem()) {
if (!p->d.exp.isEmpty()) if (!p->exp.isEmpty())
return QString::fromLatin1("(%1).%2").arg(QString::fromLatin1(p->d.exp), d.name); return QString::fromLatin1("(%1).%2").arg(QString::fromLatin1(p->exp), name);
} }
return d.name; return name;
} }
QString WatchItem::displayName() const QString WatchItem::displayName() const
@@ -689,12 +669,12 @@ QString WatchItem::displayName() const
QString result; QString result;
if (!parentItem()) if (!parentItem())
return result; return result;
if (d.iname.startsWith("return")) if (iname.startsWith("return"))
result = WatchModel::tr("returned value"); result = WatchModel::tr("returned value");
else if (d.name == QLatin1String("*")) else if (name == QLatin1String("*"))
result = QLatin1Char('*') + parentItem()->d.name; result = QLatin1Char('*') + parentItem()->name;
else else
result = watchModel()->removeNamespaces(d.name); result = watchModel()->removeNamespaces(name);
// Simplyfy names that refer to base classes. // Simplyfy names that refer to base classes.
if (result.startsWith(QLatin1Char('['))) { if (result.startsWith(QLatin1Char('['))) {
@@ -709,20 +689,20 @@ QString WatchItem::displayName() const
QString WatchItem::displayValue() const QString WatchItem::displayValue() const
{ {
QString result = watchModel()->removeNamespaces(truncateValue(formattedValue())); QString result = watchModel()->removeNamespaces(truncateValue(formattedValue()));
if (result.isEmpty() && d.address) if (result.isEmpty() && address)
result += QString::fromLatin1("@0x" + QByteArray::number(d.address, 16)); result += QString::fromLatin1("@0x" + QByteArray::number(address, 16));
// if (d.origaddr) // if (origaddr)
// result += QString::fromLatin1(" (0x" + QByteArray::number(d.origaddr, 16) + ')'); // result += QString::fromLatin1(" (0x" + QByteArray::number(origaddr, 16) + ')');
return result; return result;
} }
QString WatchItem::displayType() const QString WatchItem::displayType() const
{ {
QString result = d.displayedType.isEmpty() QString result = displayedType.isEmpty()
? niceTypeHelper(d.type) ? niceTypeHelper(type)
: d.displayedType; : displayedType;
if (d.bitsize) if (bitsize)
result += QString::fromLatin1(":%1").arg(d.bitsize); result += QString::fromLatin1(":%1").arg(bitsize);
result.remove(QLatin1Char('\'')); result.remove(QLatin1Char('\''));
result = watchModel()->removeNamespaces(result); result = watchModel()->removeNamespaces(result);
return result; return result;
@@ -733,13 +713,13 @@ QColor WatchItem::valueColor() const
static const QColor red(200, 0, 0); static const QColor red(200, 0, 0);
static const QColor gray(140, 140, 140); static const QColor gray(140, 140, 140);
if (watchModel()) { if (watchModel()) {
if (!d.valueEnabled) if (!valueEnabled)
return gray; return gray;
if (!watchModel()->contentIsValid() && !d.isInspect()) if (!watchModel()->contentIsValid() && !isInspect())
return gray; return gray;
if (d.value.isEmpty()) // This might still show 0x... if (value.isEmpty()) // This might still show 0x...
return gray; return gray;
if (d.value != watchModel()->m_valueCache.value(d.iname)) if (value != watchModel()->m_valueCache.value(iname))
return red; return red;
} }
return QColor(); return QColor();
@@ -752,10 +732,10 @@ QVariant WatchItem::data(int column, int role) const
return QVariant(editType()); return QVariant(editType());
case LocalsNameRole: case LocalsNameRole:
return QVariant(d.name); return QVariant(name);
case LocalsIntegerBaseRole: case LocalsIntegerBaseRole:
if (isPointerType(d.type)) // Pointers using 0x-convention if (isPointerType(type)) // Pointers using 0x-convention
return QVariant(16); return QVariant(16);
return QVariant(formatToIntegerBase(itemFormat())); return QVariant(formatToIntegerBase(itemFormat()));
@@ -767,9 +747,9 @@ QVariant WatchItem::data(int column, int role) const
return editValue(); return editValue();
case 2: case 2:
// FIXME:: To be tested: Can debuggers handle those? // FIXME:: To be tested: Can debuggers handle those?
if (!d.displayedType.isEmpty()) if (!displayedType.isEmpty())
return d.displayedType; return displayedType;
return QString::fromUtf8(d.type); return QString::fromUtf8(type);
} }
} }
@@ -786,7 +766,7 @@ QVariant WatchItem::data(int column, int role) const
case Qt::ToolTipRole: case Qt::ToolTipRole:
return boolSetting(UseToolTipsInLocalsView) return boolSetting(UseToolTipsInLocalsView)
? d.toToolTip() : QVariant(); ? toToolTip() : QVariant();
case Qt::ForegroundRole: case Qt::ForegroundRole:
if (column == 1) if (column == 1)
@@ -796,51 +776,51 @@ QVariant WatchItem::data(int column, int role) const
return expression(); return expression();
case LocalsRawExpressionRole: case LocalsRawExpressionRole:
return d.exp; return exp;
case LocalsINameRole: case LocalsINameRole:
return d.iname; return iname;
case LocalsExpandedRole: case LocalsExpandedRole:
return watchModel()->m_expandedINames.contains(d.iname); return watchModel()->m_expandedINames.contains(iname);
case LocalsTypeFormatListRole: case LocalsTypeFormatListRole:
return QVariant::fromValue(watchModel()->typeFormatList(d)); return QVariant::fromValue(typeFormatList());
case LocalsTypeRole: case LocalsTypeRole:
return watchModel()->removeNamespaces(displayType()); return watchModel()->removeNamespaces(displayType());
case LocalsRawTypeRole: case LocalsRawTypeRole:
return QString::fromLatin1(d.type); return QString::fromLatin1(type);
case LocalsTypeFormatRole: case LocalsTypeFormatRole:
return theTypeFormats.value(stripForFormat(d.type), AutomaticFormat); return theTypeFormats.value(stripForFormat(type), AutomaticFormat);
case LocalsIndividualFormatRole: case LocalsIndividualFormatRole:
return theIndividualFormats.value(d.iname, AutomaticFormat); return theIndividualFormats.value(iname, AutomaticFormat);
case LocalsRawValueRole: case LocalsRawValueRole:
return d.value; return value;
case LocalsObjectAddressRole: case LocalsObjectAddressRole:
return d.address; return address;
case LocalsPointerAddressRole: case LocalsPointerAddressRole:
return d.origaddr; return origaddr;
case LocalsIsWatchpointAtObjectAddressRole: { case LocalsIsWatchpointAtObjectAddressRole: {
BreakpointParameters bp(WatchpointAtAddress); BreakpointParameters bp(WatchpointAtAddress);
bp.address = d.address; bp.address = address;
return watchModel()->engine()->breakHandler()->findWatchpoint(bp) != 0; return watchModel()->engine()->breakHandler()->findWatchpoint(bp) != 0;
} }
case LocalsSizeRole: case LocalsSizeRole:
return QVariant(d.size); return QVariant(size);
case LocalsIsWatchpointAtPointerAddressRole: case LocalsIsWatchpointAtPointerAddressRole:
if (isPointerType(d.type)) { if (isPointerType(type)) {
BreakpointParameters bp(WatchpointAtAddress); BreakpointParameters bp(WatchpointAtAddress);
bp.address = pointerValue(d.value); bp.address = pointerValue(value);
return watchModel()->engine()->breakHandler()->findWatchpoint(bp) != 0; return watchModel()->engine()->breakHandler()->findWatchpoint(bp) != 0;
} }
return false; return false;
@@ -871,7 +851,6 @@ bool WatchModel::setData(const QModelIndex &idx, const QVariant &value, int role
WatchItem *item = static_cast<WatchItem *>(itemFromIndex(idx)); WatchItem *item = static_cast<WatchItem *>(itemFromIndex(idx));
QTC_ASSERT(item, return false); QTC_ASSERT(item, return false);
const WatchData &data = item->d;
switch (role) { switch (role) {
case Qt::EditRole: case Qt::EditRole:
@@ -881,35 +860,35 @@ bool WatchModel::setData(const QModelIndex &idx, const QVariant &value, int role
break; break;
} }
case 1: // Change value case 1: // Change value
engine()->assignValueInDebugger(&data, item->expression(), value); engine()->assignValueInDebugger(item, item->expression(), value);
break; break;
case 2: // TODO: Implement change type. case 2: // TODO: Implement change type.
engine()->assignValueInDebugger(&data, item->expression(), value); engine()->assignValueInDebugger(item, item->expression(), value);
break; break;
} }
case LocalsExpandedRole: case LocalsExpandedRole:
if (value.toBool()) { if (value.toBool()) {
// Should already have been triggered by fetchMore() // Should already have been triggered by fetchMore()
//QTC_CHECK(m_expandedINames.contains(data.iname)); //QTC_CHECK(m_expandedINames.contains(item->iname));
m_expandedINames.insert(data.iname); m_expandedINames.insert(item->iname);
} else { } else {
m_expandedINames.remove(data.iname); m_expandedINames.remove(item->iname);
} }
emit columnAdjustmentRequested(); emit columnAdjustmentRequested();
break; break;
case LocalsTypeFormatRole: case LocalsTypeFormatRole:
m_handler->setFormat(data.type, value.toInt()); m_handler->setFormat(item->type, value.toInt());
engine()->updateWatchData(data); engine()->updateWatchItem(item);
break; break;
case LocalsIndividualFormatRole: { case LocalsIndividualFormatRole: {
const int format = value.toInt(); const int format = value.toInt();
if (format == AutomaticFormat) if (format == AutomaticFormat)
theIndividualFormats.remove(data.iname); theIndividualFormats.remove(item->iname);
else else
theIndividualFormats[data.iname] = format; theIndividualFormats[item->iname] = format;
engine()->updateWatchData(data); engine()->updateWatchItem(item);
break; break;
} }
} }
@@ -931,29 +910,29 @@ Qt::ItemFlags WatchItem::flags(int column) const
const Qt::ItemFlags notEditable = Qt::ItemIsSelectable | Qt::ItemIsEnabled; const Qt::ItemFlags notEditable = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
const Qt::ItemFlags editable = notEditable | Qt::ItemIsEditable; const Qt::ItemFlags editable = notEditable | Qt::ItemIsEditable;
if (d.isWatcher()) { if (isWatcher()) {
if (state != InferiorStopOk if (state != InferiorStopOk
&& state != DebuggerNotReady && state != DebuggerNotReady
&& state != DebuggerFinished && state != DebuggerFinished
&& !engine->hasCapability(AddWatcherWhileRunningCapability)) && !engine->hasCapability(AddWatcherWhileRunningCapability))
return Qt::ItemFlags(); return Qt::ItemFlags();
if (column == 0 && d.iname.count('.') == 1) if (column == 0 && iname.count('.') == 1)
return editable; // Watcher names are editable. return editable; // Watcher names are editable.
if (!d.name.isEmpty()) { if (!name.isEmpty()) {
// FIXME: Forcing types is not implemented yet. // FIXME: Forcing types is not implemented yet.
//if (idx.column() == 2) //if (idx.column() == 2)
// return editable; // Watcher types can be set by force. // return editable; // Watcher types can be set by force.
if (column == 1 && d.valueEditable) if (column == 1 && valueEditable)
return editable; // Watcher values are sometimes editable. return editable; // Watcher values are sometimes editable.
} }
} else if (d.isLocal()) { } else if (isLocal()) {
if (state != InferiorStopOk && !engine->hasCapability(AddWatcherWhileRunningCapability)) if (state != InferiorStopOk && !engine->hasCapability(AddWatcherWhileRunningCapability))
return Qt::ItemFlags(); return Qt::ItemFlags();
if (column == 1 && d.valueEditable) if (column == 1 && valueEditable)
return editable; // Locals values are sometimes editable. return editable; // Locals values are sometimes editable.
} else if (d.isInspect()) { } else if (isInspect()) {
if (column == 1 && d.valueEditable) if (column == 1 && valueEditable)
return editable; // Inspector values are sometimes editable. return editable; // Inspector values are sometimes editable.
} }
return notEditable; return notEditable;
@@ -991,26 +970,26 @@ QString WatchModel::nameForFormat(int format)
return QString(); return QString();
} }
TypeFormatList WatchModel::typeFormatList(const WatchData &data) const TypeFormatList WatchItem::typeFormatList() const
{ {
TypeFormatList formats; TypeFormatList formats;
// Types supported by dumpers: // Types supported by dumpers:
// Hack: Compensate for namespaces. // Hack: Compensate for namespaces.
QString type = QLatin1String(stripForFormat(data.type)); QString t = QLatin1String(stripForFormat(type));
int pos = type.indexOf(QLatin1String("::Q")); int pos = t.indexOf(QLatin1String("::Q"));
if (pos >= 0 && type.count(QLatin1Char(':')) == 2) if (pos >= 0 && t.count(QLatin1Char(':')) == 2)
type.remove(0, pos + 2); t.remove(0, pos + 2);
pos = type.indexOf(QLatin1Char('<')); pos = t.indexOf(QLatin1Char('<'));
if (pos >= 0) if (pos >= 0)
type.truncate(pos); t.truncate(pos);
type.replace(QLatin1Char(':'), QLatin1Char('_')); t.replace(QLatin1Char(':'), QLatin1Char('_'));
QStringList reported = m_reportedTypeFormats.value(type); QStringList reported = watchModel()->m_reportedTypeFormats.value(t);
for (int i = 0, n = reported.size(); i != n; ++i) for (int i = 0, n = reported.size(); i != n; ++i)
formats.append(TypeFormatItem(reported.at(i), i)); formats.append(TypeFormatItem(reported.at(i), i));
// Fixed artificial string and pointer types. // Fixed artificial string and pointer types.
if (data.origaddr || isPointerType(data.type)) { if (origaddr || isPointerType(type)) {
formats.append(RawFormat); formats.append(RawFormat);
formats.append(Latin1StringFormat); formats.append(Latin1StringFormat);
formats.append(SeparateLatin1StringFormat); formats.append(SeparateLatin1StringFormat);
@@ -1023,7 +1002,7 @@ TypeFormatList WatchModel::typeFormatList(const WatchData &data) const
formats.append(Array100Format); formats.append(Array100Format);
formats.append(Array1000Format); formats.append(Array1000Format);
formats.append(Array10000Format); formats.append(Array10000Format);
} else if (data.type.contains("char[") || data.type.contains("char [")) { } else if (type.contains("char[") || type.contains("char [")) {
formats.append(RawFormat); formats.append(RawFormat);
formats.append(Latin1StringFormat); formats.append(Latin1StringFormat);
formats.append(SeparateLatin1StringFormat); formats.append(SeparateLatin1StringFormat);
@@ -1036,14 +1015,14 @@ TypeFormatList WatchModel::typeFormatList(const WatchData &data) const
// Fixed artificial floating point types. // Fixed artificial floating point types.
bool ok = false; bool ok = false;
data.value.toDouble(&ok); value.toDouble(&ok);
if (ok) { if (ok) {
formats.append(CompactFloatFormat); formats.append(CompactFloatFormat);
formats.append(ScientificFloatFormat); formats.append(ScientificFloatFormat);
} }
// Fixed artificial integral types. // Fixed artificial integral types.
QString v = data.value; QString v = value;
if (v.startsWith(QLatin1Char('-'))) if (v.startsWith(QLatin1Char('-')))
v = v.mid(1); v = v.mid(1);
v.toULongLong(&ok, 10); v.toULongLong(&ok, 10);
@@ -1093,25 +1072,11 @@ static bool watchDataLessThan(const QByteArray &iname1, int sortId1,
return qstrcmp(iname1.constData() + cmpPos1, iname2.constData() + cmpPos2) < 0; return qstrcmp(iname1.constData() + cmpPos1, iname2.constData() + cmpPos2) < 0;
} }
// Sort key for watch data consisting of iname and numerical sort id.
struct WatchDataSortKey
{
explicit WatchDataSortKey(const WatchData &wd)
: iname(wd.iname), sortId(wd.sortId) {}
QByteArray iname;
int sortId;
};
inline bool operator<(const WatchDataSortKey &k1, const WatchDataSortKey &k2)
{
return watchDataLessThan(k1.iname, k1.sortId, k2.iname, k2.sortId);
}
bool watchItemSorter(const TreeItem *item1, const TreeItem *item2) bool watchItemSorter(const TreeItem *item1, const TreeItem *item2)
{ {
const WatchItem *it1 = static_cast<const WatchItem *>(item1); const WatchItem *it1 = static_cast<const WatchItem *>(item1);
const WatchItem *it2 = static_cast<const WatchItem *>(item2); const WatchItem *it2 = static_cast<const WatchItem *>(item2);
return watchDataLessThan(it1->d.iname, it1->d.sortId, it2->d.iname, it2->d.sortId); return watchDataLessThan(it1->iname, it1->sortId, it2->iname, it2->sortId);
} }
static int findInsertPosition(const QVector<TreeItem *> &list, const WatchItem *item) static int findInsertPosition(const QVector<TreeItem *> &list, const WatchItem *item)
@@ -1121,27 +1086,38 @@ static int findInsertPosition(const QVector<TreeItem *> &list, const WatchItem *
return it - list.begin(); return it - list.begin();
} }
int WatchItem::requestedFormat() const void WatchModel::reinsertAllData()
{ {
int format = theIndividualFormats.value(d.iname, AutomaticFormat); QList<WatchData> list;
if (format == AutomaticFormat) foreach (TreeItem *child, rootItem()->children())
format = theTypeFormats.value(stripForFormat(d.type), AutomaticFormat); reinsertAllDataHelper(static_cast<WatchItem *>(child), &list);
return format;
reinitialize(true);
for (int i = 0, n = list.size(); i != n; ++i) {
const WatchData &data = list.at(i);
QTC_ASSERT(!data.iname.isEmpty(), qDebug() << data.toString(); return);
// Add new entry.
WatchItem *parent = findItem(parentName(data.iname));
QTC_ASSERT(parent, return);
WatchItem *newItem = new WatchItem(data);
newItem->sortChildren(&watchItemSorter);
const int row = findInsertPosition(parent->children(), newItem);
parent->insertChild(row, newItem);
if (m_expandedINames.contains(parent->iname)) {
emit inameIsExpanded(parent->iname);
emit itemIsExpanded(indexFromItem(parent));
}
showEditValue(data);
}
} }
void WatchItem::showInEditorHelper(QString *contents, int depth) const int WatchItem::requestedFormat() const
{ {
const QChar tab = QLatin1Char('\t'); int format = theIndividualFormats.value(iname, AutomaticFormat);
const QChar nl = QLatin1Char('\n'); if (format == AutomaticFormat)
contents->append(QString(depth, tab)); format = theTypeFormats.value(stripForFormat(type), AutomaticFormat);
contents->append(d.name); return format;
contents->append(tab);
contents->append(d.value);
contents->append(tab);
contents->append(QString::fromLatin1(d.type));
contents->append(nl);
foreach (const TreeItem *child, children())
static_cast<const WatchItem *>(child)->showInEditorHelper(contents, depth + 1);
} }
void WatchModel::setCurrentItem(const QByteArray &iname) void WatchModel::setCurrentItem(const QByteArray &iname)
@@ -1165,15 +1141,13 @@ WatchHandler::WatchHandler(DebuggerEngine *engine)
m_contentsValid = false; m_contentsValid = false;
m_contentsValid = true; // FIXME m_contentsValid = true; // FIXME
m_resetLocationScheduled = false; m_resetLocationScheduled = false;
m_separatedView = new SeparatedView;
} }
WatchHandler::~WatchHandler() WatchHandler::~WatchHandler()
{ {
delete m_separatedView;
m_separatedView = 0;
// Do it manually to prevent calling back in model destructors // Do it manually to prevent calling back in model destructors
// after m_cache is destroyed. // after m_cache is destroyed.
m_model->disconnect();
delete m_model; delete m_model;
m_model = 0; m_model = 0;
} }
@@ -1185,7 +1159,7 @@ void WatchHandler::cleanup()
saveWatchers(); saveWatchers();
m_model->reinitialize(); m_model->reinitialize();
emit m_model->updateFinished(); emit m_model->updateFinished();
m_separatedView->hide(); m_model->m_separatedView.hide();
} }
void WatchHandler::insertItem(WatchItem *item) void WatchHandler::insertItem(WatchItem *item)
@@ -1195,44 +1169,19 @@ void WatchHandler::insertItem(WatchItem *item)
void WatchModel::insertItem(WatchItem *item) void WatchModel::insertItem(WatchItem *item)
{ {
WatchItem *existing = findItem(item->d.iname); WatchItem *existing = findItem(item->iname);
if (existing) if (existing)
removeItem(existing); removeItem(existing);
WatchItem *parent = findItem(parentName(item->d.iname)); //item->walkTree([item](TreeItem *sub) { sub->sortChildren(&watchItemSorter); });
item->sortChildren(&watchItemSorter);
WatchItem *parent = findItem(parentName(item->iname));
QTC_ASSERT(parent, return); QTC_ASSERT(parent, return);
const int row = findInsertPosition(parent->children(), item); const int row = findInsertPosition(parent->children(), item);
parent->insertChild(row, item); parent->insertChild(row, item);
} }
void WatchModel::insertDataItem(const WatchData &data)
{
QTC_ASSERT(!data.iname.isEmpty(), qDebug() << data.toString(); return);
if (WatchItem *item = findItem(data.iname)) {
// Remove old children.
item->fetchTriggered = false;
item->removeChildren();
// Overwrite old entry.
item->d = data;
item->update();
} else {
// Add new entry.
WatchItem *parent = findItem(parentName(data.iname));
QTC_ASSERT(parent, return);
WatchItem *newItem = new WatchItem;
newItem->d = data;
const int row = findInsertPosition(parent->children(), newItem);
parent->insertChild(row, newItem);
if (m_expandedINames.contains(parent->d.iname)) {
emit inameIsExpanded(parent->d.iname);
emit itemIsExpanded(indexFromItem(parent));
}
}
m_handler->showEditValue(data);
}
void WatchModel::reexpandItems() void WatchModel::reexpandItems()
{ {
foreach (const QByteArray &iname, m_expandedINames) { foreach (const QByteArray &iname, m_expandedINames) {
@@ -1248,11 +1197,6 @@ void WatchModel::reexpandItems()
} }
} }
void WatchHandler::insertData(const WatchData &data)
{
m_model->insertDataItem(data);
}
void WatchHandler::removeAllData(bool includeInspectData) void WatchHandler::removeAllData(bool includeInspectData)
{ {
m_model->reinitialize(includeInspectData); m_model->reinitialize(includeInspectData);
@@ -1265,7 +1209,7 @@ void WatchHandler::resetValueCache()
TreeItem *root = m_model->rootItem(); TreeItem *root = m_model->rootItem();
root->walkTree([this, root](TreeItem *item) { root->walkTree([this, root](TreeItem *item) {
auto watchItem = static_cast<WatchItem *>(item); auto watchItem = static_cast<WatchItem *>(item);
m_model->m_valueCache[watchItem->d.iname] = watchItem->d.value; m_model->m_valueCache[watchItem->iname] = watchItem->value;
}); });
} }
@@ -1307,8 +1251,8 @@ void WatchHandler::removeItemByIName(const QByteArray &iname)
WatchItem *item = m_model->findItem(iname); WatchItem *item = m_model->findItem(iname);
if (!item) if (!item)
return; return;
if (item->d.isWatcher()) { if (item->isWatcher()) {
theWatcherNames.remove(item->d.exp); theWatcherNames.remove(item->exp);
saveWatchers(); saveWatchers();
} }
m_model->removeItem(item); m_model->removeItem(item);
@@ -1330,19 +1274,18 @@ void WatchHandler::watchExpression(const QString &exp0, const QString &name)
theWatcherNames[exp] = theWatcherCount++; theWatcherNames[exp] = theWatcherCount++;
WatchData data; auto item = new WatchItem;
data.exp = exp; item->exp = exp;
data.name = name.isEmpty() ? exp0 : name; item->name = name.isEmpty() ? exp0 : name;
data.iname = watcherName(exp); item->iname = watcherName(exp);
saveWatchers(); saveWatchers();
if (m_engine->state() == DebuggerNotReady) { if (m_engine->state() == DebuggerNotReady) {
data.setAllUnneeded(); item->setAllUnneeded();
data.setValue(QString(QLatin1Char(' '))); item->setValue(QString(QLatin1Char(' ')));
data.setHasChildren(false); m_model->insertItem(item);
m_model->insertDataItem(data);
} else { } else {
m_engine->updateWatchData(data); m_engine->updateWatchItem(item);
} }
updateWatchersWindow(); updateWatchersWindow();
} }
@@ -1371,12 +1314,12 @@ static void swapEndian(char *d, int nchar)
} }
} }
void WatchHandler::showEditValue(const WatchData &data) void WatchModel::showEditValue(const WatchData &data)
{ {
const QByteArray key = data.address ? data.hexAddress() : data.iname; const QByteArray key = data.address ? data.hexAddress() : data.iname;
switch (data.editformat) { switch (data.editformat) {
case StopDisplay: case StopDisplay:
m_separatedView->removeObject(data.iname); m_separatedView.removeObject(data.iname);
break; break;
case DisplayImageData: case DisplayImageData:
case DisplayImageFile: { // QImage case DisplayImageFile: { // QImage
@@ -1414,7 +1357,7 @@ void WatchHandler::showEditValue(const WatchData &data)
tr("%1 Object at %2").arg(QLatin1String(data.type), tr("%1 Object at %2").arg(QLatin1String(data.type),
QLatin1String(data.hexAddress())) : QLatin1String(data.hexAddress())) :
tr("%1 Object at Unknown Address").arg(QLatin1String(data.type)); tr("%1 Object at Unknown Address").arg(QLatin1String(data.type));
ImageViewer *v = m_separatedView->prepareObject<ImageViewer>(key, title); ImageViewer *v = m_separatedView.prepareObject<ImageViewer>(key, title);
v->setProperty(INameProperty, data.iname); v->setProperty(INameProperty, data.iname);
v->setImage(im); v->setImage(im);
break; break;
@@ -1430,7 +1373,7 @@ void WatchHandler::showEditValue(const WatchData &data)
str = QString::fromLatin1(ba.constData(), ba.size()); str = QString::fromLatin1(ba.constData(), ba.size());
else if (data.editformat == DisplayUtf8String) else if (data.editformat == DisplayUtf8String)
str = QString::fromUtf8(ba.constData(), ba.size()); str = QString::fromUtf8(ba.constData(), ba.size());
QTextEdit *t = m_separatedView->prepareObject<QTextEdit>(key, data.name); QTextEdit *t = m_separatedView.prepareObject<QTextEdit>(key, data.name);
t->setProperty(INameProperty, data.iname); t->setProperty(INameProperty, data.iname);
t->setText(str); t->setText(str);
break; break;
@@ -1557,37 +1500,29 @@ WatchModelBase *WatchHandler::model() const
return m_model; return m_model;
} }
const WatchData *WatchHandler::watchData(const QModelIndex &idx) const const WatchItem *WatchHandler::watchItem(const QModelIndex &idx) const
{ {
TreeItem *item = m_model->itemFromIndex(idx); return static_cast<WatchItem *>(m_model->itemFromIndex(idx));
return item ? &static_cast<WatchItem *>(item)->d : 0;
} }
void WatchHandler::fetchMore(const QByteArray &iname) const void WatchHandler::fetchMore(const QByteArray &iname) const
{ {
WatchItem *item = m_model->findItem(iname); if (WatchItem *item = m_model->findItem(iname))
if (item)
item->fetchMore(); item->fetchMore();
} }
const WatchData *WatchHandler::findData(const QByteArray &iname) const
{
const WatchItem *item = m_model->findItem(iname);
return item ? &item->d : 0;
}
WatchItem *WatchHandler::findItem(const QByteArray &iname) const WatchItem *WatchHandler::findItem(const QByteArray &iname) const
{ {
return m_model->findItem(iname); return m_model->findItem(iname);
} }
const WatchData *WatchHandler::findCppLocalVariable(const QString &name) const const WatchItem *WatchHandler::findCppLocalVariable(const QString &name) const
{ {
// Can this be found as a local variable? // Can this be found as a local variable?
const QByteArray localsPrefix("local."); const QByteArray localsPrefix("local.");
QByteArray iname = localsPrefix + name.toLatin1(); QByteArray iname = localsPrefix + name.toLatin1();
if (const WatchData *wd = findData(iname)) if (const WatchItem *item = findItem(iname))
return wd; return item;
// // Nope, try a 'local.this.m_foo'. // // Nope, try a 'local.this.m_foo'.
// iname.insert(localsPrefix.size(), "this."); // iname.insert(localsPrefix.size(), "this.");
// if (const WatchData *wd = findData(iname)) // if (const WatchData *wd = findData(iname))
@@ -1615,9 +1550,9 @@ int WatchHandler::format(const QByteArray &iname) const
{ {
int result = AutomaticFormat; int result = AutomaticFormat;
if (const WatchItem *item = m_model->findItem(iname)) { if (const WatchItem *item = m_model->findItem(iname)) {
result = theIndividualFormats.value(item->d.iname, AutomaticFormat); result = theIndividualFormats.value(item->iname, AutomaticFormat);
if (result == AutomaticFormat) if (result == AutomaticFormat)
result = theTypeFormats.value(stripForFormat(item->d.type), AutomaticFormat); result = theTypeFormats.value(stripForFormat(item->type), AutomaticFormat);
} }
return result; return result;
} }
@@ -1716,10 +1651,21 @@ void WatchHandler::addTypeFormats(const QByteArray &type, const QStringList &for
m_model->m_reportedTypeFormats.insert(QLatin1String(stripForFormat(type)), formats); m_model->m_reportedTypeFormats.insert(QLatin1String(stripForFormat(type)), formats);
} }
static void showInEditorHelper(const WatchItem *item, QTextStream &ts, int depth)
{
const QChar tab = QLatin1Char('\t');
const QChar nl = QLatin1Char('\n');
ts << QString(depth, tab) << item->name << tab << item->value << tab
<< item->type << nl;
foreach (const TreeItem *child, item->children())
showInEditorHelper(static_cast<const WatchItem *>(child), ts, depth + 1);
}
QString WatchHandler::editorContents() QString WatchHandler::editorContents()
{ {
QString contents; QString contents;
m_model->root()->showInEditorHelper(&contents, 0); QTextStream ts(&contents);
showInEditorHelper(m_model->root(), ts, 0);
return contents; return contents;
} }
@@ -1733,22 +1679,6 @@ DumperTypeFormats WatchHandler::typeFormats() const
return m_model->m_reportedTypeFormats; return m_model->m_reportedTypeFormats;
} }
void WatchHandler::editTypeFormats(bool includeLocals, const QByteArray &iname)
{
Q_UNUSED(includeLocals);
TypeFormatsDialog dlg(0);
//QHashIterator<QString, QStringList> it(m_reportedTypeFormats);
QList<QString> l = m_model->m_reportedTypeFormats.keys();
Utils::sort(l);
foreach (const QString &ba, l) {
int f = iname.isEmpty() ? AutomaticFormat : format(iname);
dlg.addTypeFormats(ba, m_model->m_reportedTypeFormats.value(ba), f);
}
if (dlg.exec())
setTypeFormats(dlg.typeFormats());
}
void WatchHandler::scheduleResetLocation() void WatchHandler::scheduleResetLocation()
{ {
m_contentsValid = false; m_contentsValid = false;
@@ -1828,30 +1758,30 @@ WatchItem::WatchItem()
WatchItem::WatchItem(const QByteArray &i, const QString &n) WatchItem::WatchItem(const QByteArray &i, const QString &n)
{ {
fetchTriggered = false; fetchTriggered = false;
d.iname = i; iname = i;
d.name = n; name = n;
} }
WatchItem::WatchItem(const WatchData &data) WatchItem::WatchItem(const WatchData &data)
: d(data), fetchTriggered(false) : WatchData(data), fetchTriggered(false)
{ {
} }
WatchItem::WatchItem(const GdbMi &data) WatchItem::WatchItem(const GdbMi &data)
: fetchTriggered(false) : fetchTriggered(false)
{ {
d.iname = data["iname"].data(); iname = data["iname"].data();
GdbMi wname = data["wname"]; GdbMi wname = data["wname"];
if (wname.isValid()) // Happens (only) for watched expressions. if (wname.isValid()) // Happens (only) for watched expressions.
d.name = QString::fromUtf8(QByteArray::fromHex(wname.data())); name = QString::fromUtf8(QByteArray::fromHex(wname.data()));
else else
d.name = QString::fromLatin1(data["name"].data()); name = QString::fromLatin1(data["name"].data());
parseWatchData(data); parseWatchData(data);
if (wname.isValid()) if (wname.isValid())
d.exp = d.name.toUtf8(); exp = name.toUtf8();
} }
WatchItem *WatchItem::parentItem() const WatchItem *WatchItem::parentItem() const
@@ -1872,8 +1802,9 @@ WatchModel *WatchItem::watchModel()
void WatchItem::parseWatchData(const GdbMi &input) void WatchItem::parseWatchData(const GdbMi &input)
{ {
auto itemHandler = [this](const WatchData &data) { auto itemHandler = [this](const WatchData &data) {
d = data; WatchData::operator=(data);
}; };
auto childHandler = [this](const WatchData &innerData, const GdbMi &innerInput) { auto childHandler = [this](const WatchData &innerData, const GdbMi &innerInput) {
WatchItem *item = new WatchItem(innerData); WatchItem *item = new WatchItem(innerData);
item->parseWatchData(innerInput); item->parseWatchData(innerInput);
@@ -1889,10 +1820,8 @@ void WatchItem::parseWatchData(const GdbMi &input)
decodeArrayData(itemAdder, childTemplate, encodedData, encoding); decodeArrayData(itemAdder, childTemplate, encodedData, encoding);
}; };
parseChildrenData(d, input, itemHandler, childHandler, arrayDecoder); parseChildrenData(*this, input, itemHandler, childHandler, arrayDecoder);
} }
} // namespace Internal } // namespace Internal
} // namespace Debugger } // namespace Debugger
#include "watchhandler.moc"

View File

@@ -35,17 +35,34 @@
#include <utils/treemodel.h> #include <utils/treemodel.h>
#include <QPointer>
#include <QVector> #include <QVector>
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
class DebuggerCommand; class DebuggerCommand;
class SeparatedView; class DebuggerEngine;
class WatchModel; class WatchModel;
class WatchItem : public Utils::TreeItem class TypeFormatItem
{
public:
TypeFormatItem() : format(-1) {}
TypeFormatItem(const QString &display, int format);
QString display;
int format;
};
class TypeFormatList : public QVector<TypeFormatItem>
{
public:
using QVector::append;
void append(int format);
TypeFormatItem find(int format) const;
};
class WatchItem : public Utils::TreeItem, public WatchData
{ {
public: public:
WatchItem(); WatchItem();
@@ -53,14 +70,6 @@ public:
explicit WatchItem(const WatchData &data); explicit WatchItem(const WatchData &data);
explicit WatchItem(const GdbMi &data); explicit WatchItem(const GdbMi &data);
WatchItem *parentItem() const;
const WatchModel *watchModel() const;
WatchModel *watchModel();
QVariant data(int column, int role) const;
Qt::ItemFlags flags(int column) const;
bool canFetchMore() const;
void fetchMore(); void fetchMore();
QString displayName() const; QString displayName() const;
@@ -76,12 +85,19 @@ public:
QColor valueColor() const; QColor valueColor() const;
int requestedFormat() const; int requestedFormat() const;
void showInEditorHelper(QString *contents, int depth) const;
WatchItem *findItem(const QByteArray &iname); WatchItem *findItem(const QByteArray &iname);
void parseWatchData(const GdbMi &input);
public: private:
WatchData d; WatchItem *parentItem() const;
const WatchModel *watchModel() const;
WatchModel *watchModel();
TypeFormatList typeFormatList() const;
bool canFetchMore() const;
QVariant data(int column, int role) const;
Qt::ItemFlags flags(int column) const;
void parseWatchData(const GdbMi &input);
bool fetchTriggered; bool fetchTriggered;
}; };
@@ -125,35 +141,6 @@ enum DisplayFormat
ScientificFloatFormat, ScientificFloatFormat,
}; };
class TypeFormatItem
{
public:
TypeFormatItem() : format(-1) {}
TypeFormatItem(const QString &display, int format);
QString display;
int format;
};
class TypeFormatList : public QVector<TypeFormatItem>
{
public:
using QVector::append;
void append(int format);
TypeFormatItem find(int format) const;
};
} // namespace Internal
} // namespace Debugger
Q_DECLARE_METATYPE(Debugger::Internal::TypeFormatList)
namespace Debugger {
namespace Internal {
class DebuggerEngine;
class UpdateParameters class UpdateParameters
{ {
public: public:
@@ -196,13 +183,10 @@ public:
void watchVariable(const QString &exp); void watchVariable(const QString &exp);
Q_SLOT void clearWatches(); Q_SLOT void clearWatches();
void showEditValue(const WatchData &data); const WatchItem *watchItem(const QModelIndex &) const;
const WatchData *watchData(const QModelIndex &) const;
void fetchMore(const QByteArray &iname) const; void fetchMore(const QByteArray &iname) const;
const WatchData *findData(const QByteArray &iname) const;
WatchItem *findItem(const QByteArray &iname) const; WatchItem *findItem(const QByteArray &iname) const;
const WatchData *findCppLocalVariable(const QString &name) const; const WatchItem *findCppLocalVariable(const QString &name) const;
bool hasItem(const QByteArray &iname) const; bool hasItem(const QByteArray &iname) const;
void loadSessionData(); void loadSessionData();
@@ -229,7 +213,6 @@ public:
QByteArray watcherName(const QByteArray &exp); QByteArray watcherName(const QByteArray &exp);
QString editorContents(); QString editorContents();
void editTypeFormats(bool includeLocals, const QByteArray &iname);
void scheduleResetLocation(); void scheduleResetLocation();
void resetLocation(); void resetLocation();
@@ -238,7 +221,6 @@ public:
void updateWatchersWindow(); void updateWatchersWindow();
void appendFormatRequests(DebuggerCommand *cmd); void appendFormatRequests(DebuggerCommand *cmd);
void insertData(const WatchData &data); // DEPRECATED
void insertItem(WatchItem *item); // Takes ownership. void insertItem(WatchItem *item); // Takes ownership.
void removeItemByIName(const QByteArray &iname); void removeItemByIName(const QByteArray &iname);
void removeAllData(bool includeInspectData = false); void removeAllData(bool includeInspectData = false);
@@ -259,7 +241,6 @@ private:
WatchModel *m_model; // Owned. WatchModel *m_model; // Owned.
DebuggerEngine *m_engine; // Not owned. DebuggerEngine *m_engine; // Not owned.
SeparatedView *m_separatedView; // Owned.
bool m_contentsValid; bool m_contentsValid;
bool m_resetLocationScheduled; bool m_resetLocationScheduled;
@@ -269,5 +250,6 @@ private:
} // namespace Debugger } // namespace Debugger
Q_DECLARE_METATYPE(Debugger::Internal::UpdateParameters) Q_DECLARE_METATYPE(Debugger::Internal::UpdateParameters)
Q_DECLARE_METATYPE(Debugger::Internal::TypeFormatList)
#endif // DEBUGGER_WATCHHANDLER_H #endif // DEBUGGER_WATCHHANDLER_H