forked from qt-creator/qt-creator
Debugger: Make the time stamp recording option work for single items
Should help to drill down to individual expensive dumpers. Change-Id: I983ba075231784f71dd9d5c3bda375a3ee508bf6 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -270,6 +270,7 @@ class DumperBase:
|
|||||||
# Later set, or not set:
|
# Later set, or not set:
|
||||||
self.stringCutOff = 10000
|
self.stringCutOff = 10000
|
||||||
self.displayStringLimit = 100
|
self.displayStringLimit = 100
|
||||||
|
self.useTimeStamps = False
|
||||||
|
|
||||||
self.typesReported = {}
|
self.typesReported = {}
|
||||||
self.typesToReport = {}
|
self.typesToReport = {}
|
||||||
@@ -329,6 +330,7 @@ class DumperBase:
|
|||||||
self.showQObjectNames = int(args.get('qobjectnames', '1'))
|
self.showQObjectNames = int(args.get('qobjectnames', '1'))
|
||||||
self.nativeMixed = int(args.get('nativemixed', '0'))
|
self.nativeMixed = int(args.get('nativemixed', '0'))
|
||||||
self.autoDerefPointers = int(args.get('autoderef', '0'))
|
self.autoDerefPointers = int(args.get('autoderef', '0'))
|
||||||
|
self.useTimeStamps = int(args.get('timestamps', '0'))
|
||||||
self.partialVariable = args.get('partialvar', '')
|
self.partialVariable = args.get('partialvar', '')
|
||||||
self.uninitialized = args.get('uninitialized', [])
|
self.uninitialized = args.get('uninitialized', [])
|
||||||
self.uninitialized = list(map(lambda x: self.hexdecode(x), self.uninitialized))
|
self.uninitialized = list(map(lambda x: self.hexdecode(x), self.uninitialized))
|
||||||
@@ -422,6 +424,8 @@ class DumperBase:
|
|||||||
self.currentIName = item.iname
|
self.currentIName = item.iname
|
||||||
self.currentValue = ReportItem();
|
self.currentValue = ReportItem();
|
||||||
self.currentType = ReportItem();
|
self.currentType = ReportItem();
|
||||||
|
if self.useTimeStamps:
|
||||||
|
item.startTime = time.time()
|
||||||
|
|
||||||
def exitSubItem(self, item, exType, exValue, exTraceBack):
|
def exitSubItem(self, item, exType, exValue, exTraceBack):
|
||||||
#warn('CURRENT VALUE: %s: %s %s' %
|
#warn('CURRENT VALUE: %s: %s %s' %
|
||||||
@@ -431,6 +435,8 @@ class DumperBase:
|
|||||||
showException('SUBITEM', exType, exValue, exTraceBack)
|
showException('SUBITEM', exType, exValue, exTraceBack)
|
||||||
self.putSpecialValue('notaccessible')
|
self.putSpecialValue('notaccessible')
|
||||||
self.putNumChild(0)
|
self.putNumChild(0)
|
||||||
|
if self.useTimeStamps:
|
||||||
|
self.put('time="%s",' % (time.time() - item.startTime))
|
||||||
if not self.isCli:
|
if not self.isCli:
|
||||||
try:
|
try:
|
||||||
if self.currentType.value:
|
if self.currentType.value:
|
||||||
|
@@ -1114,6 +1114,7 @@ void CdbEngine::doUpdateLocals(const UpdateParameters &updateParameters)
|
|||||||
cmd.arg("dyntype", boolSetting(UseDynamicType));
|
cmd.arg("dyntype", boolSetting(UseDynamicType));
|
||||||
cmd.arg("partialvar", updateParameters.partialVariable);
|
cmd.arg("partialvar", updateParameters.partialVariable);
|
||||||
cmd.arg("qobjectnames", boolSetting(ShowQObjectNames));
|
cmd.arg("qobjectnames", boolSetting(ShowQObjectNames));
|
||||||
|
cmd.arg("timestamps", boolSetting(LogTimeStamps));
|
||||||
|
|
||||||
StackFrame frame = stackHandler()->currentFrame();
|
StackFrame frame = stackHandler()->currentFrame();
|
||||||
cmd.arg("context", frame.context);
|
cmd.arg("context", frame.context);
|
||||||
|
@@ -4743,6 +4743,7 @@ void GdbEngine::doUpdateLocals(const UpdateParameters ¶ms)
|
|||||||
cmd.arg("autoderef", boolSetting(AutoDerefPointers));
|
cmd.arg("autoderef", boolSetting(AutoDerefPointers));
|
||||||
cmd.arg("dyntype", boolSetting(UseDynamicType));
|
cmd.arg("dyntype", boolSetting(UseDynamicType));
|
||||||
cmd.arg("qobjectnames", boolSetting(ShowQObjectNames));
|
cmd.arg("qobjectnames", boolSetting(ShowQObjectNames));
|
||||||
|
cmd.arg("timestamps", boolSetting(LogTimeStamps));
|
||||||
|
|
||||||
StackFrame frame = stackHandler()->currentFrame();
|
StackFrame frame = stackHandler()->currentFrame();
|
||||||
cmd.arg("context", frame.context);
|
cmd.arg("context", frame.context);
|
||||||
|
@@ -764,6 +764,7 @@ void LldbEngine::doUpdateLocals(const UpdateParameters ¶ms)
|
|||||||
cmd.arg("dyntype", boolSetting(UseDynamicType));
|
cmd.arg("dyntype", boolSetting(UseDynamicType));
|
||||||
cmd.arg("partialvar", params.partialVariable);
|
cmd.arg("partialvar", params.partialVariable);
|
||||||
cmd.arg("qobjectnames", boolSetting(ShowQObjectNames));
|
cmd.arg("qobjectnames", boolSetting(ShowQObjectNames));
|
||||||
|
cmd.arg("timestamps", boolSetting(LogTimeStamps));
|
||||||
|
|
||||||
StackFrame frame = stackHandler()->currentFrame();
|
StackFrame frame = stackHandler()->currentFrame();
|
||||||
cmd.arg("context", frame.context);
|
cmd.arg("context", frame.context);
|
||||||
|
@@ -363,6 +363,10 @@ void WatchItem::parseHelper(const GdbMi &input, bool maySort)
|
|||||||
if (mi.isValid())
|
if (mi.isValid())
|
||||||
exp = mi.data();
|
exp = mi.data();
|
||||||
|
|
||||||
|
mi = input["time"];
|
||||||
|
if (mi.isValid())
|
||||||
|
time = mi.data().toFloat();
|
||||||
|
|
||||||
mi = input["sortgroup"];
|
mi = input["sortgroup"];
|
||||||
if (mi.isValid())
|
if (mi.isValid())
|
||||||
sortGroup = mi.toInt();
|
sortGroup = mi.toInt();
|
||||||
@@ -462,6 +466,8 @@ void WatchItem::parse(const GdbMi &data, bool maySort)
|
|||||||
|
|
||||||
if (wname.isValid())
|
if (wname.isValid())
|
||||||
exp = name;
|
exp = name;
|
||||||
|
|
||||||
|
time = data["time"].data().toFloat();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format a tooltip row with aligned colon.
|
// Format a tooltip row with aligned colon.
|
||||||
@@ -508,6 +514,7 @@ QString WatchItem::toToolTip() const
|
|||||||
if (size)
|
if (size)
|
||||||
formatToolTipRow(str, tr("Static Object Size"), tr("%n bytes", nullptr, size));
|
formatToolTipRow(str, tr("Static Object Size"), tr("%n bytes", nullptr, size));
|
||||||
formatToolTipRow(str, tr("Internal ID"), internalName());
|
formatToolTipRow(str, tr("Internal ID"), internalName());
|
||||||
|
formatToolTipRow(str, tr("Creation Time in ms"), QString::number(int(time * 1000)));
|
||||||
str << "</table></body></html>";
|
str << "</table></body></html>";
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@@ -99,6 +99,7 @@ public:
|
|||||||
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 outdated; // \internal item is to be removed.
|
bool outdated; // \internal item is to be removed.
|
||||||
|
double time = 0; // Time used on the dumper side to produce this item
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void parseHelper(const GdbMi &input, bool maySort);
|
void parseHelper(const GdbMi &input, bool maySort);
|
||||||
|
@@ -484,7 +484,7 @@ WatchModel::WatchModel(WatchHandler *handler, DebuggerEngine *engine)
|
|||||||
|
|
||||||
m_contentsValid = true;
|
m_contentsValid = true;
|
||||||
|
|
||||||
setHeader({tr("Name"), tr("Value"), tr("Type")});
|
setHeader({tr("Name"), tr("Time"), tr("Value"), tr("Type")});
|
||||||
m_localsRoot = new WatchItem;
|
m_localsRoot = new WatchItem;
|
||||||
m_localsRoot->iname = "local";
|
m_localsRoot->iname = "local";
|
||||||
m_localsRoot->name = tr("Locals");
|
m_localsRoot->name = tr("Locals");
|
||||||
@@ -901,7 +901,7 @@ static QColor valueColor(const WatchItem *item, int column)
|
|||||||
if (const WatchModel *model = watchModel(item)) {
|
if (const WatchModel *model = watchModel(item)) {
|
||||||
if (!model->m_contentsValid && !item->isInspect()) {
|
if (!model->m_contentsValid && !item->isInspect()) {
|
||||||
color = Theme::Debugger_WatchItem_ValueInvalid;
|
color = Theme::Debugger_WatchItem_ValueInvalid;
|
||||||
} else if (column == 1) {
|
} else if (column == WatchModel::ValueColumn) {
|
||||||
if (!item->valueEnabled)
|
if (!item->valueEnabled)
|
||||||
color = Theme::Debugger_WatchItem_ValueInvalid;
|
color = Theme::Debugger_WatchItem_ValueInvalid;
|
||||||
else if (!model->m_contentsValid && !item->isInspect())
|
else if (!model->m_contentsValid && !item->isInspect())
|
||||||
@@ -1011,11 +1011,13 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
|
|||||||
|
|
||||||
case Qt::EditRole: {
|
case Qt::EditRole: {
|
||||||
switch (column) {
|
switch (column) {
|
||||||
case 0:
|
case TimeColumn:
|
||||||
|
return item->time;
|
||||||
|
case NameColumn:
|
||||||
return item->expression();
|
return item->expression();
|
||||||
case 1:
|
case ValueColumn:
|
||||||
return item->editValue();
|
return item->editValue();
|
||||||
case 2:
|
case TypeColumn:
|
||||||
return item->type;
|
return item->type;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1023,11 +1025,13 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
|
|||||||
|
|
||||||
case Qt::DisplayRole: {
|
case Qt::DisplayRole: {
|
||||||
switch (column) {
|
switch (column) {
|
||||||
case 0:
|
case TimeColumn:
|
||||||
|
return int(1000 * item->time);
|
||||||
|
case NameColumn:
|
||||||
return displayName(item);
|
return displayName(item);
|
||||||
case 1:
|
case ValueColumn:
|
||||||
return displayValue(item);
|
return displayValue(item);
|
||||||
case 2:
|
case TypeColumn:
|
||||||
return displayType(item);
|
return displayType(item);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1129,14 +1133,14 @@ bool WatchModel::setData(const QModelIndex &idx, const QVariant &value, int role
|
|||||||
switch (role) {
|
switch (role) {
|
||||||
case Qt::EditRole:
|
case Qt::EditRole:
|
||||||
switch (idx.column()) {
|
switch (idx.column()) {
|
||||||
case 0: {
|
case NameColumn: {
|
||||||
m_handler->updateWatchExpression(item, value.toString().trimmed());
|
m_handler->updateWatchExpression(item, value.toString().trimmed());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1: // Change value
|
case ValueColumn: // Change value
|
||||||
m_engine->assignValueInDebugger(item, item->expression(), value);
|
m_engine->assignValueInDebugger(item, item->expression(), value);
|
||||||
break;
|
break;
|
||||||
case 2: // TODO: Implement change type.
|
case TypeColumn: // TODO: Implement change type.
|
||||||
m_engine->assignValueInDebugger(item, item->expression(), value);
|
m_engine->assignValueInDebugger(item, item->expression(), value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1206,20 +1210,20 @@ Qt::ItemFlags WatchModel::flags(const QModelIndex &idx) const
|
|||||||
|
|
||||||
if (item->isWatcher()) {
|
if (item->isWatcher()) {
|
||||||
if (state == InferiorUnrunnable)
|
if (state == InferiorUnrunnable)
|
||||||
return (column == 0 && item->iname.count('.') == 1) ? editable : notEditable;
|
return (column == NameColumn && item->iname.count('.') == 1) ? editable : notEditable;
|
||||||
|
|
||||||
if (isRunning && !m_engine->hasCapability(AddWatcherWhileRunningCapability))
|
if (isRunning && !m_engine->hasCapability(AddWatcherWhileRunningCapability))
|
||||||
return notEditable;
|
return notEditable;
|
||||||
if (column == 0 && item->iname.count('.') == 1)
|
if (column == NameColumn && item->iname.count('.') == 1)
|
||||||
return editable; // Watcher names are editable.
|
return editable; // Watcher names are editable.
|
||||||
if (column == 1 && item->arrayIndex >= 0)
|
if (column == ValueColumn && item->arrayIndex >= 0)
|
||||||
return editable;
|
return editable;
|
||||||
|
|
||||||
if (!item->name.isEmpty()) {
|
if (!item->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 && item->valueEditable && !item->elided)
|
if (column == ValueColumn && item->valueEditable && !item->elided)
|
||||||
return editable; // Watcher values are sometimes editable.
|
return editable; // Watcher values are sometimes editable.
|
||||||
}
|
}
|
||||||
} else if (item->isLocal()) {
|
} else if (item->isLocal()) {
|
||||||
@@ -1227,12 +1231,12 @@ Qt::ItemFlags WatchModel::flags(const QModelIndex &idx) const
|
|||||||
return notEditable;
|
return notEditable;
|
||||||
if (isRunning && !m_engine->hasCapability(AddWatcherWhileRunningCapability))
|
if (isRunning && !m_engine->hasCapability(AddWatcherWhileRunningCapability))
|
||||||
return notEditable;
|
return notEditable;
|
||||||
if (column == 1 && item->valueEditable && !item->elided)
|
if (column == ValueColumn && item->valueEditable && !item->elided)
|
||||||
return editable; // Locals values are sometimes editable.
|
return editable; // Locals values are sometimes editable.
|
||||||
if (column == 1 && item->arrayIndex >= 0)
|
if (column == ValueColumn && item->arrayIndex >= 0)
|
||||||
return editable;
|
return editable;
|
||||||
} else if (item->isInspect()) {
|
} else if (item->isInspect()) {
|
||||||
if (column == 1 && item->valueEditable)
|
if (column == ValueColumn && item->valueEditable)
|
||||||
return editable; // Inspector values are sometimes editable.
|
return editable; // Inspector values are sometimes editable.
|
||||||
}
|
}
|
||||||
return notEditable;
|
return notEditable;
|
||||||
|
@@ -46,6 +46,8 @@ class WatchModelBase : public Utils::TreeModel<WatchItem, WatchItem>
|
|||||||
public:
|
public:
|
||||||
WatchModelBase() = default;
|
WatchModelBase() = default;
|
||||||
|
|
||||||
|
enum { NameColumn, TimeColumn, ValueColumn, TypeColumn };
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void currentIndexRequested(const QModelIndex &idx);
|
void currentIndexRequested(const QModelIndex &idx);
|
||||||
void itemIsExpanded(const QModelIndex &idx);
|
void itemIsExpanded(const QModelIndex &idx);
|
||||||
|
@@ -53,6 +53,9 @@ WatchTreeView::WatchTreeView(WatchType type)
|
|||||||
|
|
||||||
connect(this, &QTreeView::expanded, this, &WatchTreeView::expandNode);
|
connect(this, &QTreeView::expanded, this, &WatchTreeView::expandNode);
|
||||||
connect(this, &QTreeView::collapsed, this, &WatchTreeView::collapseNode);
|
connect(this, &QTreeView::collapsed, this, &WatchTreeView::collapseNode);
|
||||||
|
|
||||||
|
connect(action(LogTimeStamps), &QAction::triggered,
|
||||||
|
this, &WatchTreeView::updateTimeColumn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WatchTreeView::expandNode(const QModelIndex &idx)
|
void WatchTreeView::expandNode(const QModelIndex &idx)
|
||||||
@@ -96,6 +99,14 @@ void WatchTreeView::setModel(QAbstractItemModel *model)
|
|||||||
connect(watchModel, &WatchModelBase::updateFinished,
|
connect(watchModel, &WatchModelBase::updateFinished,
|
||||||
this, &WatchTreeView::hideProgressIndicator);
|
this, &WatchTreeView::hideProgressIndicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateTimeColumn();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WatchTreeView::updateTimeColumn()
|
||||||
|
{
|
||||||
|
if (header())
|
||||||
|
header()->setSectionHidden(WatchModelBase::TimeColumn, !boolSetting(LogTimeStamps));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WatchTreeView::handleItemIsExpanded(const QModelIndex &idx)
|
void WatchTreeView::handleItemIsExpanded(const QModelIndex &idx)
|
||||||
|
@@ -56,6 +56,7 @@ private:
|
|||||||
void resetHelper();
|
void resetHelper();
|
||||||
void expandNode(const QModelIndex &idx);
|
void expandNode(const QModelIndex &idx);
|
||||||
void collapseNode(const QModelIndex &idx);
|
void collapseNode(const QModelIndex &idx);
|
||||||
|
void updateTimeColumn();
|
||||||
void adjustSlider();
|
void adjustSlider();
|
||||||
|
|
||||||
void doItemsLayout() override;
|
void doItemsLayout() override;
|
||||||
|
Reference in New Issue
Block a user