diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index e1d04a03f79..d44c528778a 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -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: diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index a4028091b66..12a24dc286f 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -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); diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index c8983d0b6bc..b51dc1f33cc 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -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); diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index 16eac8a6e7a..7e62db91fdb 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -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); diff --git a/src/plugins/debugger/watchdata.cpp b/src/plugins/debugger/watchdata.cpp index c37e9d46a2b..7abde55e875 100644 --- a/src/plugins/debugger/watchdata.cpp +++ b/src/plugins/debugger/watchdata.cpp @@ -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 << ""; return res; } diff --git a/src/plugins/debugger/watchdata.h b/src/plugins/debugger/watchdata.h index e6131c39cdc..15146d9616e 100644 --- a/src/plugins/debugger/watchdata.h +++ b/src/plugins/debugger/watchdata.h @@ -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); diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index 8087e776387..3e95668d52d 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -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; diff --git a/src/plugins/debugger/watchhandler.h b/src/plugins/debugger/watchhandler.h index 5be7c7f58ec..39c8630d751 100644 --- a/src/plugins/debugger/watchhandler.h +++ b/src/plugins/debugger/watchhandler.h @@ -46,6 +46,8 @@ class WatchModelBase : public Utils::TreeModel public: WatchModelBase() = default; + enum { NameColumn, TimeColumn, ValueColumn, TypeColumn }; + signals: void currentIndexRequested(const QModelIndex &idx); void itemIsExpanded(const QModelIndex &idx); diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp index cf31ff71870..9da95b351e9 100644 --- a/src/plugins/debugger/watchwindow.cpp +++ b/src/plugins/debugger/watchwindow.cpp @@ -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) diff --git a/src/plugins/debugger/watchwindow.h b/src/plugins/debugger/watchwindow.h index bd75e005491..a2ede3cbe4b 100644 --- a/src/plugins/debugger/watchwindow.h +++ b/src/plugins/debugger/watchwindow.h @@ -56,6 +56,7 @@ private: void resetHelper(); void expandNode(const QModelIndex &idx); void collapseNode(const QModelIndex &idx); + void updateTimeColumn(); void adjustSlider(); void doItemsLayout() override;