Debugger/MemoryView: Recurse over children.

Color all available children if available instead of just
first order children. Remove member variable struct and
pass range vector representing area directly to recursion.
This commit is contained in:
Friedemann Kleint
2011-04-12 15:43:00 +02:00
parent 9a0e0f5ea3
commit fc2e7263d5

View File

@@ -153,43 +153,42 @@ static inline QString nameOf(const QModelIndex &m)
static inline uint sizeOf(const QModelIndex &m) static inline uint sizeOf(const QModelIndex &m)
{ return m.data(LocalsSizeRole).toUInt(); } { return m.data(LocalsSizeRole).toUInt(); }
// Helper functionality to obtain a address-sorted list of member variables // Helper functionality to indicate the area of a member variable in
// of a watch model index and its size. Restrict this to the size passed // a vector representing the memory area by a unique color
// in since static members can be contained that are in different areas. // number and tooltip. Parts of it will be overwritten when recursing
struct MemberVariable // over the children.
{
MemberVariable(quint64 a = 0, uint s = 0, const QString &n = QString()) :
address(a), size(s), name(n) {}
quint64 address; typedef QPair<int, QString> ColorNumberToolTipPair;
uint size; typedef QVector<ColorNumberToolTipPair> ColorNumberToolTipVector;
QString name;
};
bool lessThanMV(const MemberVariable &m1, const MemberVariable &m2) static int memberVariableRecursion(const QModelIndex &m,
{ const QString &name,
return m1.address < m2.address; quint64 start, quint64 end,
} int *colorNumberIn,
ColorNumberToolTipVector *cnmv)
static QVector<MemberVariable> sortedMemberVariables(const QModelIndex &m,
quint64 start, quint64 end)
{ {
int childCount = 0;
const int rowCount = m.model()->rowCount(m); const int rowCount = m.model()->rowCount(m);
if (!rowCount) if (!rowCount)
return QVector<MemberVariable>(); return childCount;
QVector<MemberVariable> result; const QString nameRoot = name + QLatin1Char('.');
result.reserve(rowCount);
for (int r = 0; r < rowCount; r++) { for (int r = 0; r < rowCount; r++) {
const QModelIndex childIndex = m.child(r, 0); const QModelIndex childIndex = m.child(r, 0);
const quint64 childAddress = addressOf(childIndex); const quint64 childAddress = addressOf(childIndex);
const uint childSize = sizeOf(childIndex); const uint childSize = sizeOf(childIndex);
if (childAddress && childAddress >= start if (childAddress && childAddress >= start
&& (childAddress + childSize) <= end) { // Non-static, within area? && (childAddress + childSize) <= end) { // Non-static, within area?
result.push_back(MemberVariable(childAddress, childSize, nameOf(childIndex))); const QString childName = nameRoot + nameOf(childIndex);
const quint64 childOffset = childAddress - start;
const QString toolTip = WatchWindow::tr("%1 at #%2").arg(childName).arg(childOffset);
const ColorNumberToolTipPair colorNumberNamePair((*colorNumberIn)++, toolTip);
const ColorNumberToolTipVector::iterator begin = cnmv->begin() + childOffset;
qFill(begin, begin + childSize, colorNumberNamePair);
childCount++;
childCount += memberVariableRecursion(childIndex, childName, start, end, colorNumberIn, cnmv);
} }
} }
qStableSort(result.begin(), result.end(), lessThanMV); return childCount;
return result;
} }
/*! /*!
@@ -197,12 +196,13 @@ static QVector<MemberVariable> sortedMemberVariables(const QModelIndex &m,
\brief Creates markup for a variable in the memory view. \brief Creates markup for a variable in the memory view.
Marks the 1st order children with alternating colors in the parent, that is, for Marks the visible children with alternating colors in the parent, that is, for
\code \code
struct Foo { struct Foo {
char c1 char c1
char c2 char c2
int x2; int x2;
QPair<int, int> pair
} }
\endcode \endcode
create something like: create something like:
@@ -213,6 +213,9 @@ static QVector<MemberVariable> sortedMemberVariables(const QModelIndex &m,
3 base color 3 base color
4 member color1 4 member color1
... ...
8 memberColor2 (pair.first)
...
12 memberColor1 (pair.second)
\endcode \endcode
Fixme: When dereferencing a pointer, the size of the pointee is not Fixme: When dereferencing a pointer, the size of the pointee is not
@@ -234,45 +237,19 @@ static inline MemoryViewWidgetMarkup
{ {
enum { debug = 0 }; enum { debug = 0 };
typedef QPair<QColor, QString> ColorNamePair;
typedef QVector<ColorNamePair> ColorNameVector;
MemoryViewWidgetMarkup result;
const QVector<MemberVariable> members = sortedMemberVariables(m, address, address + size);
// Starting out from base, create an array representing the area filled with base // Starting out from base, create an array representing the area filled with base
// color. Fill children with alternating member colors, // color. Fill children with some unique color numbers,
// leaving the padding areas of the parent colored with the base color. // leaving the padding areas of the parent colored with the base color.
if (sizeIsEstimate && members.isEmpty()) MemoryViewWidgetMarkup result;
return result; // Fixme: Exact size not known, no point in filling if no children.
const QColor baseColor = sizeIsEstimate ? defaultBackground : Qt::lightGray;
const QString name = nameOf(m); const QString name = nameOf(m);
ColorNameVector ranges(size, ColorNamePair(baseColor, name)); int colorNumber = 0;
if (!members.isEmpty()) { ColorNumberToolTipVector ranges(size, ColorNumberToolTipPair(colorNumber, name));
QColor memberColor1 = QColor(Qt::yellow).lighter(); const int childCount = memberVariableRecursion(m, name, address, address + size, &colorNumber, &ranges);
QColor memberColor2 = QColor(Qt::cyan).lighter(); if (sizeIsEstimate && !childCount)
for (int m = 0; m < members.size(); m++) { return result; // Fixme: Exact size not known, no point in filling if no children.
QColor memberColor;
if (m & 1) {
memberColor = memberColor1;
memberColor1 = memberColor1.darker(120);
} else {
memberColor = memberColor2;
memberColor2 = memberColor2.darker(120);
}
const quint64 childOffset = members.at(m).address - address;
const QString toolTip = WatchWindow::tr("%1.%2 at #%3")
.arg(name, members.at(m).name).arg(childOffset);
qFill(ranges.begin() + childOffset,
ranges.begin() + childOffset + members.at(m).size,
ColorNamePair(memberColor, toolTip));
}
}
if (debug) { if (debug) {
QDebug dbg = qDebug().nospace(); QDebug dbg = qDebug().nospace();
dbg << name << ' ' << address << ' ' << size << '\n'; dbg << name << ' ' << address << ' ' << size << '\n';
foreach (const MemberVariable &mv, members)
dbg << ' ' << mv.name << ' ' << mv.address << ' ' << mv.size << '\n';
QString name; QString name;
for (unsigned i = 0; i < size; i++) for (unsigned i = 0; i < size; i++)
if (name != ranges.at(i).second) { if (name != ranges.at(i).second) {
@@ -281,12 +258,30 @@ static inline MemoryViewWidgetMarkup
} }
} }
// Condense ranges of identical color into markup ranges. // Condense ranges of identical color into markup ranges. Assign member colors
// interchangeably.
const QColor baseColor = sizeIsEstimate ? defaultBackground : Qt::lightGray;
QColor memberColor1 = QColor(Qt::yellow).lighter();
QColor memberColor2 = QColor(Qt::cyan).lighter();
int lastColorNumber = 0;
int childNumber = 0;
for (unsigned i = 0; i < size; i++) { for (unsigned i = 0; i < size; i++) {
const ColorNamePair &range = ranges.at(i); const ColorNumberToolTipPair &range = ranges.at(i);
if (result.isEmpty() || result.back().format.background().color() != range.first) { if (result.isEmpty() || lastColorNumber != range.first) {
lastColorNumber = range.first;
QTextCharFormat format = defaultFormat; QTextCharFormat format = defaultFormat;
format.setBackground(QBrush(range.first)); if (range.first == 0) { // Base color: Parent
format.setBackground(QBrush(baseColor));
} else {
if (childNumber++ & 1) { // Alternating member colors.
format.setBackground(QBrush(memberColor1));
memberColor1 = memberColor1.darker(120);
} else {
format.setBackground(QBrush(memberColor2));
memberColor2 = memberColor2.darker(120);
}
} // color switch
result.push_back(MemoryViewWidget::Markup(address + i, 1, format, range.second)); result.push_back(MemoryViewWidget::Markup(address + i, 1, format, range.second));
} else { } else {
result.back().size++; result.back().size++;
@@ -296,8 +291,6 @@ static inline MemoryViewWidgetMarkup
if (debug) { if (debug) {
QDebug dbg = qDebug().nospace(); QDebug dbg = qDebug().nospace();
dbg << name << ' ' << address << ' ' << size << '\n'; dbg << name << ' ' << address << ' ' << size << '\n';
foreach (const MemberVariable &mv, members)
dbg << ' ' << mv.name << ' ' << mv.address << ' ' << mv.size << '\n';
QString name; QString name;
for (unsigned i = 0; i < size; i++) for (unsigned i = 0; i < size; i++)
if (name != ranges.at(i).second) { if (name != ranges.at(i).second) {