From 29322b6124769112c498c5e40c72b7b05c7186cf Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 31 Mar 2015 14:20:43 +0200 Subject: [PATCH] Debugger: Polish register view Right-align subregister values, drop the 0x prefix for hex values, add a subitem with ASCII representation and tooltips for subitems. Change-Id: I6a5764fa5ef8b2bfd916cdd828d949a82304503d Reviewed-by: Christian Stenger --- src/plugins/debugger/registerhandler.cpp | 121 ++++++++++++++++------- src/plugins/debugger/registerhandler.h | 15 ++- src/plugins/debugger/registerwindow.cpp | 35 ++++--- 3 files changed, 117 insertions(+), 54 deletions(-) diff --git a/src/plugins/debugger/registerhandler.cpp b/src/plugins/debugger/registerhandler.cpp index 8fad2eece27..545631c90f8 100644 --- a/src/plugins/debugger/registerhandler.cpp +++ b/src/plugins/debugger/registerhandler.cpp @@ -252,14 +252,29 @@ void Register::guessMissingData() fixup(this, IntegerRegister, 0); } -static QString subTypeName(RegisterKind kind, int size) +static QString subTypeName(RegisterKind kind, int size, RegisterFormat format) { - if (kind == IntegerRegister) - return QString::fromLatin1("[i%1]").arg(size * 8); - if (kind == FloatRegister) - return QString::fromLatin1("[f%1]").arg(size * 8); - QTC_ASSERT(false, /**/); - return QString(); + QString name(QLatin1Char('[')); + + switch (kind) { + case IntegerRegister: name += QLatin1Char('i'); break; + case FloatRegister: name += QLatin1Char('f'); break; + default: break; + } + + name += QString::number(size); + + switch (format) { + case BinaryFormat: name += QLatin1Char('b'); break; + case OctalFormat: name += QLatin1Char('o'); break; + case DecimalFormat: name += QLatin1Char('d'); break; + case HexadecimalFormat: name += QLatin1Char('x'); break; + case CharacterFormat: name += QLatin1Char('c'); break; + } + + name += QLatin1Char(']'); + + return name; } static uint decodeHexChar(unsigned char c) @@ -305,15 +320,29 @@ bool RegisterValue::operator==(const RegisterValue &other) return v.u64[0] == other.v.u64[0] && v.u64[1] == other.v.u64[1]; } -static QByteArray format(quint64 v, int base, int size) +static QByteArray formatRegister(quint64 v, int size, RegisterFormat format) { - QByteArray result = QByteArray::number(v, base); - if (base == 16) + QByteArray result; + if (format == HexadecimalFormat) { + result = QByteArray::number(v, 16); result.prepend(QByteArray(2*size - result.size(), '0')); + } else if (format == DecimalFormat) { + result = QByteArray::number(v, 10); + result.prepend(QByteArray(2*size - result.size(), ' ')); + } else if (format == CharacterFormat) { + if (v >= 32 && v < 127) { + result += '\''; + result += char(v); + result += '\''; + } else { + result += " "; + } + result.prepend(QByteArray(2*size - result.size(), ' ')); + } return result; } -QByteArray RegisterValue::toByteArray(int base, RegisterKind kind, int size) const +QByteArray RegisterValue::toByteArray(RegisterKind kind, int size, RegisterFormat format) const { if (!known) return "[inaccessible]"; @@ -326,15 +355,12 @@ QByteArray RegisterValue::toByteArray(int base, RegisterKind kind, int size) con QByteArray result; if (size > 8) { - result += format(v.u64[1], base, size - 8); + result += formatRegister(v.u64[1], size - 8, format); size = 8; - if (base != 16) + if (format != HexadecimalFormat) result += ','; } - result += format(v.u64[0], base, size); - if (base == 16) - result.prepend("0x"); - return result; + return result + formatRegister(v.u64[0], size, format); } RegisterValue RegisterValue::subValue(int size, int index) const @@ -367,8 +393,8 @@ RegisterValue RegisterValue::subValue(int size, int index) const class RegisterSubItem : public Utils::TreeItem { public: - RegisterSubItem(RegisterKind subKind, int subSize, int count) - : m_subKind(subKind), m_subSize(subSize), m_count(count), m_changed(false) + RegisterSubItem(RegisterKind subKind, int subSize, int count, RegisterFormat format) + : m_subKind(subKind), m_subFormat(format), m_subSize(subSize), m_count(count), m_changed(false) {} QVariant data(int column, int role) const; @@ -382,6 +408,7 @@ public: } RegisterKind m_subKind; + RegisterFormat m_subFormat; int m_subSize; int m_count; bool m_changed; @@ -398,23 +425,27 @@ public: quint64 addressValue() const; Register m_reg; - int m_base; + RegisterFormat m_format; bool m_changed; }; RegisterItem::RegisterItem(const Register ®) : - m_reg(reg), m_base(16), m_changed(true) + m_reg(reg), m_format(HexadecimalFormat), m_changed(true) { if (m_reg.kind == UnknownRegister) m_reg.guessMissingData(); if (m_reg.kind == IntegerRegister || m_reg.kind == VectorRegister) { - for (int s = m_reg.size / 2; s; s = s / 2) - appendChild(new RegisterSubItem(IntegerRegister, s, m_reg.size / s)); + for (int s = m_reg.size / 2; s; s = s / 2) { + appendChild(new RegisterSubItem(IntegerRegister, s, m_reg.size / s, HexadecimalFormat)); + appendChild(new RegisterSubItem(IntegerRegister, s, m_reg.size / s, DecimalFormat)); + if (s == 1) + appendChild(new RegisterSubItem(IntegerRegister, s, m_reg.size / s, CharacterFormat)); + } } if (m_reg.kind == IntegerRegister || m_reg.kind == VectorRegister) { for (int s = m_reg.size; s >= 4; s = s / 2) - appendChild(new RegisterSubItem(FloatRegister, s, m_reg.size / s)); + appendChild(new RegisterSubItem(FloatRegister, s, m_reg.size / s, DecimalFormat)); } } @@ -444,12 +475,12 @@ QVariant RegisterItem::data(int column, int role) const case RegisterChangedRole: return m_changed; - case RegisterNumberBaseRole: - return m_base; - case RegisterAsAddressRole: return addressValue(); + case RegisterFormatRole: + return m_format; + case Qt::DisplayRole: switch (column) { case RegisterNameColumn: { @@ -459,17 +490,17 @@ QVariant RegisterItem::data(int column, int role) const return res; } case RegisterValueColumn: { - return m_reg.value.toByteArray(m_base, m_reg.kind, m_reg.size); + return m_reg.value.toByteArray(m_reg.kind, m_reg.size, m_format); } } case Qt::ToolTipRole: return QString::fromLatin1("Current Value: %1\nPreviousValue: %2") - .arg(QString::fromLatin1(m_reg.value.toByteArray(m_base, m_reg.kind, m_reg.size))) - .arg(QString::fromLatin1(m_reg.previousValue.toByteArray(m_base, m_reg.kind, m_reg.size))); + .arg(QString::fromLatin1(m_reg.value.toByteArray(m_reg.kind, m_reg.size, m_format))) + .arg(QString::fromLatin1(m_reg.previousValue.toByteArray(m_reg.kind, m_reg.size, m_format))); case Qt::EditRole: // Edit: Unpadded for editing - return m_reg.value.toByteArray(m_base, m_reg.kind, m_reg.size); + return m_reg.value.toByteArray(m_reg.kind, m_reg.size, m_format); case Qt::TextAlignmentRole: return column == RegisterValueColumn ? QVariant(Qt::AlignRight) : QVariant(); @@ -486,8 +517,10 @@ QVariant RegisterSubItem::data(int column, int role) const case RegisterChangedRole: return m_changed; - case RegisterNumberBaseRole: - return 16; + case RegisterFormatRole: { + RegisterItem *registerItem = static_cast(parent()); + return int(registerItem->m_format); + } case RegisterAsAddressRole: return 0; @@ -495,20 +528,32 @@ QVariant RegisterSubItem::data(int column, int role) const case Qt::DisplayRole: switch (column) { case RegisterNameColumn: - return subTypeName(m_subKind, m_subSize); + return subTypeName(m_subKind, m_subSize, m_subFormat); case RegisterValueColumn: { QTC_ASSERT(parent(), return QVariant()); RegisterItem *registerItem = static_cast(parent()); RegisterValue value = registerItem->m_reg.value; QByteArray ba; for (int i = 0; i != m_count; ++i) { - ba += value.subValue(m_subSize, i).toByteArray(16, m_subKind, m_subSize); int tab = 5 * (i + 1) * m_subSize; - ba += QByteArray(tab - ba.size(), ' '); + QByteArray b = value.subValue(m_subSize, i).toByteArray(m_subKind, m_subSize, m_subFormat); + ba += QByteArray(tab - ba.size() - b.size(), ' '); + ba += b; } return ba; } } + + case Qt::ToolTipRole: + if (m_subKind == IntegerRegister) { + if (m_subFormat == CharacterFormat) + return RegisterHandler::tr("Content as ASCII Characters"); + else + return RegisterHandler::tr("Content as %1-bit Integer Values").arg(8 * m_subSize); + } + if (m_subKind == FloatRegister) + return RegisterHandler::tr("Contents as %1-bit Floating Point Values").arg(8 * m_subSize); + default: break; } @@ -553,11 +598,11 @@ void RegisterHandler::updateRegister(const Register &r) } } -void RegisterHandler::setNumberBase(const QByteArray &name, int base) +void RegisterHandler::setNumberFormat(const QByteArray &name, RegisterFormat format) { RegisterItem *reg = m_registerByName.value(name, 0); QTC_ASSERT(reg, return); - reg->m_base = base; + reg->m_format = format; QModelIndex index = indexFromItem(reg); emit dataChanged(index, index); } diff --git a/src/plugins/debugger/registerhandler.h b/src/plugins/debugger/registerhandler.h index 2f3a7b186b6..1d42a85edfe 100644 --- a/src/plugins/debugger/registerhandler.h +++ b/src/plugins/debugger/registerhandler.h @@ -52,7 +52,7 @@ enum RegisterDataRole RegisterNameRole = Qt::UserRole, RegisterIsBigRole, RegisterChangedRole, - RegisterNumberBaseRole, + RegisterFormatRole, RegisterAsAddressRole }; @@ -66,6 +66,15 @@ enum RegisterKind OtherRegister }; +enum RegisterFormat +{ + CharacterFormat, + HexadecimalFormat, + DecimalFormat, + OctalFormat, + BinaryFormat +}; + class RegisterValue { public: @@ -73,7 +82,7 @@ public: void operator=(const QByteArray &ba); bool operator==(const RegisterValue &other); bool operator!=(const RegisterValue &other) { return !operator==(other); } - QByteArray toByteArray(int base, RegisterKind kind, int size) const; + QByteArray toByteArray(RegisterKind kind, int size, RegisterFormat format) const; RegisterValue subValue(int size, int index) const; union { @@ -116,7 +125,7 @@ public: void updateRegister(const Register ®); - void setNumberBase(const QByteArray &name, int base); + void setNumberFormat(const QByteArray &name, RegisterFormat format); void commitUpdates() { emit layoutChanged(); } RegisterMap registerMap() const; diff --git a/src/plugins/debugger/registerwindow.cpp b/src/plugins/debugger/registerwindow.cpp index f96e5785a3d..3862bd46e64 100644 --- a/src/plugins/debugger/registerwindow.cpp +++ b/src/plugins/debugger/registerwindow.cpp @@ -66,11 +66,20 @@ public: const QModelIndex &index) const { IntegerWatchLineEdit *lineEdit = new IntegerWatchLineEdit(parent); - const int base = index.data(RegisterNumberBaseRole).toInt(); + const RegisterFormat format = RegisterFormat(index.data(RegisterFormatRole).toInt()); const bool big = index.data(RegisterIsBigRole).toBool(); // Big integers are assumed to be hexadecimal. + int base = 16; + if (!big) { + if (format == DecimalFormat) + base = 10; + else if (format == OctalFormat) + base = 8; + else if (format == BinaryFormat) + base = 2; + } lineEdit->setBigInt(big); - lineEdit->setBase(big ? 16 : base); + lineEdit->setBase(base); lineEdit->setSigned(false); lineEdit->setAlignment(Qt::AlignRight); lineEdit->setFrame(false); @@ -91,9 +100,9 @@ public: return; IntegerWatchLineEdit *lineEdit = qobject_cast(editor); QTC_ASSERT(lineEdit, return); - const int base = index.data(RegisterNumberBaseRole).toInt(); + const RegisterFormat format = RegisterFormat(index.data(RegisterFormatRole).toInt()); QString value = lineEdit->text(); - if (base == 16 && !value.startsWith(QLatin1String("0x"))) + if (format == HexadecimalFormat && !value.startsWith(QLatin1String("0x"))) value.insert(0, QLatin1String("0x")); currentEngine()->setRegisterValue(index.data(RegisterNameRole).toByteArray(), value); } @@ -206,19 +215,19 @@ void RegisterTreeView::contextMenuEvent(QContextMenuEvent *ev) } menu.addSeparator(); - const int base = idx.data(RegisterNumberBaseRole).toInt(); + const RegisterFormat format = RegisterFormat(idx.data(RegisterFormatRole).toInt()); QAction *act16 = menu.addAction(tr("Hexadecimal")); act16->setCheckable(true); - act16->setChecked(base == 16); + act16->setChecked(format == HexadecimalFormat); QAction *act10 = menu.addAction(tr("Decimal")); act10->setCheckable(true); - act10->setChecked(base == 10); + act10->setChecked(format == DecimalFormat); QAction *act8 = menu.addAction(tr("Octal")); act8->setCheckable(true); - act8->setChecked(base == 8); + act8->setChecked(format == OctalFormat); QAction *act2 = menu.addAction(tr("Binary")); act2->setCheckable(true); - act2->setChecked(base == 2); + act2->setChecked(format == BinaryFormat); menu.addSeparator(); menu.addAction(action(SettingsDialog)); @@ -252,13 +261,13 @@ void RegisterTreeView::contextMenuEvent(QContextMenuEvent *ev) } else if (act == actShowDisassemblerAt) { engine->openDisassemblerView(Location(address)); } else if (act == act16) - handler->setNumberBase(registerName, 16); + handler->setNumberFormat(registerName, HexadecimalFormat); else if (act == act10) - handler->setNumberBase(registerName, 10); + handler->setNumberFormat(registerName, DecimalFormat); else if (act == act8) - handler->setNumberBase(registerName, 8); + handler->setNumberFormat(registerName, OctalFormat); else if (act == act2) - handler->setNumberBase(registerName, 2); + handler->setNumberFormat(registerName, BinaryFormat); } void RegisterTreeView::reloadRegisters()