diff options
author | hjk <hjk@qt.io> | 2019-06-24 14:54:47 +0200 |
---|---|---|
committer | hjk <hjk@qt.io> | 2019-06-26 06:58:03 +0000 |
commit | 32bbf2a3b381977d95de1159a085b31b62a7e2c8 (patch) | |
tree | 6a9cd6685c023fa06f87f87e04c80e7d183ef3c2 /src/plugins/debugger/stackhandler.cpp | |
parent | c39f2866c7e2520960eda715d79c52c4b7ff372b (diff) |
Debugger: Introduce a tree level above stack frames
This level is meant to take the role of current thread handler
in the long run, allowing per-thread stackviews in each engine.
For now, the additional level holds just a single, invisible
dummy item playing the role of a "current thread".
Change-Id: Ief6131500fc1aa8902f2313038a65840b80b495b
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Diffstat (limited to 'src/plugins/debugger/stackhandler.cpp')
-rw-r--r-- | src/plugins/debugger/stackhandler.cpp | 128 |
1 files changed, 72 insertions, 56 deletions
diff --git a/src/plugins/debugger/stackhandler.cpp b/src/plugins/debugger/stackhandler.cpp index aef248dc20..aeafc69fbf 100644 --- a/src/plugins/debugger/stackhandler.cpp +++ b/src/plugins/debugger/stackhandler.cpp @@ -74,32 +74,30 @@ StackHandler::StackHandler(DebuggerEngine *engine) this, &StackHandler::reloadFullStack); connect(action(MaximalStackDepth), &QAction::triggered, this, &StackHandler::reloadFullStack); + + // For now there's always only "the" current thread. + rootItem()->appendChild(new ThreadDummyItem); } StackHandler::~StackHandler() = default; -QVariant StackHandler::data(const QModelIndex &index, int role) const +QVariant SpecialStackItem::data(int column, int role) const { - if (!index.isValid() || index.row() > rowCount()) - return QVariant(); - - if (isSpecialFrame(index.row())) { - if (role == Qt::DisplayRole && index.column() == StackLevelColumn) - return tr("..."); - if (role == Qt::DisplayRole && index.column() == StackFunctionNameColumn) - return tr("<More>"); - if (role == Qt::DecorationRole && index.column() == StackLevelColumn) - return Icons::EMPTY.icon(); - return QVariant(); - } - - const StackFrameItem *frameItem = static_cast<StackFrameItem *>(itemForIndex(index)); - const StackFrame &frame = frameItem->frame; + if (role == Qt::DisplayRole && column == StackLevelColumn) + return StackHandler::tr("..."); + if (role == Qt::DisplayRole && column == StackFunctionNameColumn) + return StackHandler::tr("<More>"); + if (role == Qt::DecorationRole && column == StackLevelColumn) + return Icons::EMPTY.icon(); + return QVariant(); +} +QVariant StackFrameItem::data(int column, int role) const +{ if (role == Qt::DisplayRole) { - switch (index.column()) { + switch (column) { case StackLevelColumn: - return QString::number(index.row() + 1); + return row >= 0 ? QString::number(row + 1) : QString(); case StackFunctionNameColumn: return simplifyType(frame.function); case StackFileNameColumn: @@ -114,11 +112,8 @@ QVariant StackHandler::data(const QModelIndex &index, int role) const return QVariant(); } - if (role == Qt::DecorationRole && index.column() == StackLevelColumn) { - // Return icon that indicates whether this is the active stack frame - return (m_contentsValid && index.row() == m_currentIndex) - ? Icons::LOCATION.icon() : Icons::EMPTY.icon(); - } + if (role == Qt::DecorationRole && column == StackLevelColumn) + return handler->iconForRow(row); if (role == Qt::ToolTipRole && boolSetting(UseToolTipsInStackView)) return frame.toToolTip(); @@ -126,16 +121,18 @@ QVariant StackHandler::data(const QModelIndex &index, int role) const return QVariant(); } -Qt::ItemFlags StackHandler::flags(const QModelIndex &index) const +Qt::ItemFlags StackFrameItem::flags(int column) const { - if (index.row() >= rowCount()) - return {}; - if (index.row() == rowCount() - 1 && m_canExpand) - return StackHandlerModel::flags(index); - const StackFrame &frame = rootItem()->childAt(index.row())->frame; - const bool isValid = frame.isUsable() || m_engine->operatesByInstruction(); - return isValid && m_contentsValid - ? StackHandlerModel::flags(index) : Qt::ItemFlags(); + const bool isValid = frame.isUsable() || handler->operatesByInstruction(); + return isValid && handler->isContentsValid() + ? TreeItem::flags(column) : Qt::ItemFlags(); +} + +QIcon StackHandler::iconForRow(int row) const +{ + // Return icon that indicates whether this is the active stack frame + return (m_contentsValid && row == m_currentIndex) + ? Icons::LOCATION.icon() : Icons::EMPTY.icon(); } bool StackHandler::setData(const QModelIndex &idx, const QVariant &data, int role) @@ -154,6 +151,12 @@ bool StackHandler::setData(const QModelIndex &idx, const QVariant &data, int rol return false; } +ThreadDummyItem *StackHandler::dummyThreadItem() const +{ + QTC_ASSERT(rootItem()->childCount() == 1, return nullptr); + return rootItem()->childAt(0); +} + StackFrame StackHandler::currentFrame() const { if (m_currentIndex == -1) @@ -164,20 +167,22 @@ StackFrame StackHandler::currentFrame() const StackFrame StackHandler::frameAt(int index) const { - auto frameItem = static_cast<StackFrameItem *>(m_root->childAt(index)); + auto threadItem = dummyThreadItem(); + QTC_ASSERT(threadItem, return {}); + StackFrameItem *frameItem = threadItem->childAt(index); QTC_ASSERT(frameItem, return {}); return frameItem->frame; } int StackHandler::stackSize() const { - return rowCount() - m_canExpand; + return stackRowCount() - m_canExpand; } quint64 StackHandler::topAddress() const { - QTC_ASSERT(rowCount() > 0, return 0); - return rootItem()->childAt(0)->frame.address; + QTC_ASSERT(stackRowCount() > 0, return 0); + return frameAt(0).address; } void StackHandler::setCurrentIndex(int level) @@ -199,28 +204,39 @@ void StackHandler::setCurrentIndex(int level) void StackHandler::removeAll() { - clear(); + auto threadItem = dummyThreadItem(); + QTC_ASSERT(threadItem, return); + threadItem->removeChildren(); + setCurrentIndex(-1); } +bool StackHandler::operatesByInstruction() const +{ + return m_engine->operatesByInstruction(); +} + void StackHandler::setFrames(const StackFrames &frames, bool canExpand) { - clear(); + auto threadItem = dummyThreadItem(); + QTC_ASSERT(threadItem, return); + + threadItem->removeChildren(); - m_resetLocationScheduled = false; m_contentsValid = true; m_canExpand = canExpand; + int row = 0; for (const StackFrame &frame : frames) - rootItem()->appendChild(new StackFrameItem(frame)); + threadItem->appendChild(new StackFrameItem(this, frame, row++)); if (canExpand) - rootItem()->appendChild(new StackFrameItem(StackFrame())); + threadItem->appendChild(new SpecialStackItem(this)); - if (rowCount() >= 0) - setCurrentIndex(0); - else + if (frames.isEmpty()) m_currentIndex = -1; + else + setCurrentIndex(0); emit stackChanged(); } @@ -268,9 +284,11 @@ void StackHandler::prependFrames(const StackFrames &frames) { if (frames.isEmpty()) return; + auto threadItem = dummyThreadItem(); + QTC_ASSERT(threadItem, return); const int count = frames.size(); for (int i = count - 1; i >= 0; --i) - rootItem()->prependChild(new StackFrameItem(frames.at(i))); + threadItem->prependChild(new StackFrameItem(this, frames.at(i))); if (m_currentIndex >= 0) setCurrentIndex(m_currentIndex + count); emit stackChanged(); @@ -278,14 +296,14 @@ void StackHandler::prependFrames(const StackFrames &frames) bool StackHandler::isSpecialFrame(int index) const { - return m_canExpand && index + 1 == rowCount(); + return m_canExpand && index + 1 == stackRowCount(); } int StackHandler::firstUsableIndex() const { if (!m_engine->operatesByInstruction()) { - for (int i = 0, n = rowCount(); i != n; ++i) - if (rootItem()->childAt(i)->frame.isUsable()) + for (int i = 0, n = stackRowCount(); i != n; ++i) + if (frameAt(i).isUsable()) return i; } return 0; @@ -293,17 +311,15 @@ int StackHandler::firstUsableIndex() const void StackHandler::scheduleResetLocation() { - m_resetLocationScheduled = true; m_contentsValid = false; } -void StackHandler::resetLocation() +int StackHandler::stackRowCount() const { - if (m_resetLocationScheduled) { - beginResetModel(); - m_resetLocationScheduled = false; - endResetModel(); - } + // Only one "thread" for now. + auto threadItem = dummyThreadItem(); + QTC_ASSERT(threadItem, return 0); + return threadItem->childCount(); } // Input a function to be disassembled. Accept CDB syntax @@ -353,7 +369,7 @@ void StackHandler::saveTaskFile() } QTextStream str(&file); - forItemsAtLevel<1>([&str](StackFrameItem *item) { + forItemsAtLevel<2>([&str](StackFrameItem *item) { const StackFrame &frame = item->frame; if (frame.isUsable()) str << frame.file << '\t' << frame.line << "\tstack\tFrame #" << frame.level << '\n'; |