diff options
author | hjk <hjk@theqtcompany.com> | 2016-07-18 12:36:31 +0200 |
---|---|---|
committer | hjk <hjk@qt.io> | 2016-07-18 11:17:53 +0000 |
commit | 2d79bdc29c242a04aad3519858ad64712be4de8e (patch) | |
tree | a910e2daeaeca5ce943f33d569f2e88b8a477ad4 /src/plugins/debugger/registerhandler.cpp | |
parent | 84f1466b01e9098ae983c1f53e376e977921dad9 (diff) | |
download | qt-creator-2d79bdc29c242a04aad3519858ad64712be4de8e.tar.gz |
Debugger: Remove some uses of semi-global currentEngine()
Make use of recent TreeModel improvements in various
tool views, push more operations into the engine-
owned data models, specifically context menu creation.
Change-Id: I479c97102b9fb81611c6461c6df1cec59295179a
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Reviewed-by: hjk <hjk@qt.io>
Diffstat (limited to 'src/plugins/debugger/registerhandler.cpp')
-rw-r--r-- | src/plugins/debugger/registerhandler.cpp | 267 |
1 files changed, 227 insertions, 40 deletions
diff --git a/src/plugins/debugger/registerhandler.cpp b/src/plugins/debugger/registerhandler.cpp index e96532e60e..6d6a49f29d 100644 --- a/src/plugins/debugger/registerhandler.cpp +++ b/src/plugins/debugger/registerhandler.cpp @@ -28,13 +28,127 @@ #include "debuggerengine.h" #include "watchdelegatewidgets.h" +#include "memoryview.h" +#include "memoryagent.h" +#include "debuggeractions.h" +#include "debuggerdialogs.h" +#include "debuggercore.h" +#include "debuggerengine.h" + +#include <utils/basetreeview.h> #include <utils/qtcassert.h> +#include <utils/savedaction.h> + +#include <QDebug> +#include <QItemDelegate> +#include <QMenu> +#include <QPainter> using namespace Utils; namespace Debugger { namespace Internal { +enum RegisterColumns +{ + RegisterNameColumn, + RegisterValueColumn, + RegisterColumnCount +}; + +enum RegisterDataRole +{ + RegisterChangedRole = Qt::UserRole +}; + +/////////////////////////////////////////////////////////////////////// +// +// RegisterDelegate +// +/////////////////////////////////////////////////////////////////////// + +class RegisterDelegate : public QItemDelegate +{ +public: + RegisterDelegate() {} + + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, + const QModelIndex &index) const override + { + if (index.column() == RegisterValueColumn) { + auto lineEdit = new QLineEdit(parent); + lineEdit->setAlignment(Qt::AlignLeft); + lineEdit->setFrame(false); + return lineEdit; + } + return 0; + } + + void setEditorData(QWidget *editor, const QModelIndex &index) const override + { + auto lineEdit = qobject_cast<QLineEdit *>(editor); + QTC_ASSERT(lineEdit, return); + lineEdit->setText(index.data(Qt::EditRole).toString()); + } + + void setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const override + { + if (index.column() == RegisterValueColumn) { + auto lineEdit = qobject_cast<QLineEdit *>(editor); + QTC_ASSERT(lineEdit, return); + model->setData(index, lineEdit->text(), Qt::EditRole); + } + } + + void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, + const QModelIndex &) const override + { + editor->setGeometry(option.rect); + } + + void paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const override + { + if (index.column() == RegisterValueColumn) { + const bool paintRed = index.data(RegisterChangedRole).toBool(); + QPen oldPen = painter->pen(); + const QColor lightColor(140, 140, 140); + if (paintRed) + painter->setPen(QColor(200, 0, 0)); + else + painter->setPen(lightColor); + // FIXME: performance? this changes only on real font changes. + QFontMetrics fm(option.font); + int charWidth = qMax(fm.width(QLatin1Char('x')), fm.width(QLatin1Char('0'))); + QString str = index.data(Qt::DisplayRole).toString(); + int x = option.rect.x(); + bool light = !paintRed; + for (int i = 0; i < str.size(); ++i) { + const QChar c = str.at(i); + const int uc = c.unicode(); + if (light && (uc != 'x' && uc != '0')) { + light = false; + painter->setPen(oldPen.color()); + } + if (uc == ' ') { + light = true; + painter->setPen(lightColor); + } else { + QRect r = option.rect; + r.setX(x); + r.setWidth(charWidth); + painter->drawText(r, Qt::AlignHCenter, c); + } + x += charWidth; + } + painter->setPen(oldPen); + } else { + QItemDelegate::paint(painter, option, index); + } + } +}; + ////////////////////////////////////////////////////////////////// // // Register @@ -288,9 +402,6 @@ void RegisterValue::shiftOneDigit(uint digit, RegisterFormat format) // ////////////////////////////////////////////////////////////////// -class RegisterItem; -class RegisterSubItem; - class RegisterEditItem : public TypedTreeItem<TreeItem, RegisterSubItem> { public: @@ -308,7 +419,6 @@ public: RegisterFormat m_subFormat; }; - class RegisterSubItem : public TypedTreeItem<RegisterEditItem, RegisterItem> { public: @@ -339,7 +449,7 @@ public: class RegisterItem : public TypedTreeItem<RegisterSubItem> { public: - explicit RegisterItem(const Register ®); + RegisterItem(DebuggerEngine *engine, const Register ®); QVariant data(int column, int role) const override; bool setData(int column, const QVariant &value, int role) override; @@ -348,13 +458,14 @@ public: quint64 addressValue() const; void triggerChange(); + DebuggerEngine *m_engine; Register m_reg; - RegisterFormat m_format; - bool m_changed; + RegisterFormat m_format = HexadecimalFormat; + bool m_changed = true; }; -RegisterItem::RegisterItem(const Register ®) : - m_reg(reg), m_format(HexadecimalFormat), m_changed(true) +RegisterItem::RegisterItem(DebuggerEngine *engine, const Register ®) + : m_engine(engine), m_reg(reg), m_changed(true) { if (m_reg.kind == UnknownRegister) m_reg.guessMissingData(); @@ -395,28 +506,15 @@ quint64 RegisterItem::addressValue() const void RegisterItem::triggerChange() { QString value = "0x" + m_reg.value.toString(m_reg.kind, m_reg.size, HexadecimalFormat); - DebuggerEngine *engine = static_cast<RegisterHandler *>(model())->engine(); - engine->setRegisterValue(m_reg.name, value); + m_engine->setRegisterValue(m_reg.name, value); } QVariant RegisterItem::data(int column, int role) const { switch (role) { - case RegisterNameRole: - return m_reg.name; - - case RegisterIsBigRole: - return m_reg.value.v.u64[1] > 0; - case RegisterChangedRole: return m_changed; - case RegisterAsAddressRole: - return addressValue(); - - case RegisterFormatRole: - return m_format; - case Qt::DisplayRole: switch (column) { case RegisterNameColumn: { @@ -463,12 +561,6 @@ QVariant RegisterSubItem::data(int column, int role) const case RegisterChangedRole: return m_changed; - case RegisterFormatRole: - return int(parent()->m_format); - - case RegisterAsAddressRole: - return 0; - case Qt::DisplayRole: switch (column) { case RegisterNameColumn: @@ -521,7 +613,7 @@ QVariant RegisterSubItem::data(int column, int role) const RegisterHandler::RegisterHandler(DebuggerEngine *engine) : m_engine(engine) { - setObjectName(QLatin1String("RegisterModel")); + setObjectName("RegisterModel"); setHeader({tr("Name"), tr("Value")}); } @@ -529,7 +621,7 @@ void RegisterHandler::updateRegister(const Register &r) { RegisterItem *reg = m_registerByName.value(r.name, 0); if (!reg) { - reg = new RegisterItem(r); + reg = new RegisterItem(m_engine, r); m_registerByName[r.name] = reg; rootItem()->appendChild(reg); return; @@ -550,15 +642,6 @@ void RegisterHandler::updateRegister(const Register &r) } } -void RegisterHandler::setNumberFormat(const QString &name, RegisterFormat format) -{ - RegisterItem *reg = m_registerByName.value(name, 0); - QTC_ASSERT(reg, return); - reg->m_format = format; - QModelIndex index = indexForItem(reg); - emit dataChanged(index, index); -} - RegisterMap RegisterHandler::registerMap() const { RegisterMap result; @@ -571,6 +654,110 @@ RegisterMap RegisterHandler::registerMap() const return result; } +QVariant RegisterHandler::data(const QModelIndex &idx, int role) const +{ + if (role == BaseTreeView::ItemDelegateRole) + return QVariant::fromValue(static_cast<QAbstractItemDelegate *>(new RegisterDelegate)); + + return RegisterModel::data(idx, role); +} + +bool RegisterHandler::setData(const QModelIndex &idx, const QVariant &data, int role) +{ + if (role == BaseTreeView::ItemViewEventRole) { + ItemViewEvent ev = data.value<ItemViewEvent>(); + if (ev.type() == QEvent::ContextMenu) + return contextMenuEvent(ev); + } + + return RegisterModel::setData(idx, data, role); +} + +bool RegisterHandler::contextMenuEvent(const ItemViewEvent &ev) +{ + const bool actionsEnabled = m_engine->debuggerActionsEnabled(); + const DebuggerState state = m_engine->state(); + + RegisterItem *registerItem = firstLevelItemForIndex(ev.index()); + RegisterSubItem *registerSubItem = secondLevelItemForIndex(ev.index()); + + const quint64 address = registerItem ? registerItem->addressValue() : 0; + const QString registerName = registerItem ? registerItem->m_reg.name : QString(); + + auto menu = new QMenu; + + addAction(menu, tr("Reload Register Listing"), + m_engine->hasCapability(RegisterCapability) + && (state == InferiorStopOk || state == InferiorUnrunnable), + [this] { m_engine->reloadRegisters(); }); + + menu->addSeparator(); + + addAction(menu, tr("Open Memory View at Value of Register %1 0x%2") + .arg(registerName).arg(address, 0, 16), + tr("Open Memory View at Value of Register"), + address, + [this, registerName, address] { + MemoryViewSetupData data; + data.startAddress = address; + data.flags = DebuggerEngine::MemoryTrackRegister|DebuggerEngine::MemoryView; + data.registerName = registerName; + m_engine->openMemoryView(data); + }); + + addAction(menu, tr("Open Memory Editor at 0x%1").arg(address, 0, 16), + tr("Open Memory Editor"), + address && actionsEnabled && m_engine->hasCapability(ShowMemoryCapability), + [this, registerName, address] { + MemoryViewSetupData data; + data.startAddress = address; + data.registerName = registerName; + data.markup = RegisterMemoryView::registerMarkup(address, registerName); + data.title = RegisterMemoryView::title(registerName); + m_engine->openMemoryView(data); + }); + + addAction(menu, tr("Open Disassembler at 0x%1").arg(address, 0, 16), + tr("Open Disassembler"), + address && m_engine->hasCapability(DisassemblerCapability), + [this, address] { m_engine->openDisassemblerView(Location(address)); }); + + addAction(menu, tr("Open Disassembler..."), + m_engine->hasCapability(DisassemblerCapability), + [this, address] { + AddressDialog dialog; + if (address) + dialog.setAddress(address); + if (dialog.exec() == QDialog::Accepted) + m_engine->openDisassemblerView(Location(dialog.address())); + }); + + menu->addSeparator(); + + const RegisterFormat currentFormat = registerItem + ? registerItem->m_format + : registerSubItem + ? registerSubItem->parent()->m_format + : HexadecimalFormat; + + auto addFormatAction = [this, menu, currentFormat, registerItem](const QString &display, RegisterFormat format) { + addCheckableAction(menu, display, registerItem, currentFormat == format, [this, registerItem, format] { + registerItem->m_format = format; + registerItem->update(); + }); + }; + + addFormatAction(tr("Hexadecimal"), HexadecimalFormat); + addFormatAction(tr("DecimalFormat"), DecimalFormat); + addFormatAction(tr("Octal"), OctalFormat); + addFormatAction(tr("Binary"), BinaryFormat); + + menu->addSeparator(); + menu->addAction(action(SettingsDialog)); + menu->popup(ev.globalPos()); + return true; +} + QVariant RegisterEditItem::data(int column, int role) const { switch (role) { |