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