forked from qt-creator/qt-creator
debugger: make register contents editable (gdb only for now)
This commit is contained in:
@@ -227,7 +227,6 @@ DebuggerSettings *DebuggerSettings::instance()
|
|||||||
item->setText(tr("Synchronize breakpoints"));
|
item->setText(tr("Synchronize breakpoints"));
|
||||||
instance->insertItem(SynchronizeBreakpoints, item);
|
instance->insertItem(SynchronizeBreakpoints, item);
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Settings
|
// Settings
|
||||||
//
|
//
|
||||||
|
@@ -75,6 +75,7 @@ MemoryViewAgent::MemoryViewAgent(DebuggerManager *manager, const QString &addr)
|
|||||||
{
|
{
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
init(addr.toUInt(&ok, 0));
|
init(addr.toUInt(&ok, 0));
|
||||||
|
//qDebug() << " ADDRESS: " << addr << addr.toUInt(&ok, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryViewAgent::~MemoryViewAgent()
|
MemoryViewAgent::~MemoryViewAgent()
|
||||||
|
@@ -88,7 +88,6 @@
|
|||||||
// of the engine.
|
// of the engine.
|
||||||
using namespace Debugger::Internal;
|
using namespace Debugger::Internal;
|
||||||
|
|
||||||
IDebuggerEngine *createGdbEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *);
|
|
||||||
IDebuggerEngine *createWinEngine(DebuggerManager *, bool /* cmdLineEnabled */, QList<Core::IOptionsPage*> *)
|
IDebuggerEngine *createWinEngine(DebuggerManager *, bool /* cmdLineEnabled */, QList<Core::IOptionsPage*> *)
|
||||||
#ifdef CDB_ENABLED
|
#ifdef CDB_ENABLED
|
||||||
;
|
;
|
||||||
@@ -102,6 +101,8 @@ IDebuggerEngine *createTcfEngine(DebuggerManager *parent, QList<Core::IOptionsPa
|
|||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
IDebuggerEngine *createGdbEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *);
|
||||||
|
|
||||||
QDebug operator<<(QDebug str, const DebuggerStartParameters &p)
|
QDebug operator<<(QDebug str, const DebuggerStartParameters &p)
|
||||||
{
|
{
|
||||||
QDebug nospace = str.nospace();
|
QDebug nospace = str.nospace();
|
||||||
@@ -1430,6 +1431,12 @@ void DebuggerManager::reloadFullStack()
|
|||||||
m_engine->reloadFullStack();
|
m_engine->reloadFullStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DebuggerManager::setRegisterValue(int nr, const QString &value)
|
||||||
|
{
|
||||||
|
if (m_engine)
|
||||||
|
m_engine->setRegisterValue(nr, value);
|
||||||
|
}
|
||||||
|
|
||||||
bool DebuggerManager::isReverseDebugging() const
|
bool DebuggerManager::isReverseDebugging() const
|
||||||
{
|
{
|
||||||
return m_reverseDirectionAction->isChecked();
|
return m_reverseDirectionAction->isChecked();
|
||||||
@@ -1448,7 +1455,6 @@ void DebuggerManager::setSessionValue(const QString &name, const QVariant &value
|
|||||||
emit setSessionValueRequested(name, value);
|
emit setSessionValueRequested(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Testing
|
// Testing
|
||||||
|
@@ -319,6 +319,7 @@ public slots:
|
|||||||
void executeDebuggerCommand(const QString &command);
|
void executeDebuggerCommand(const QString &command);
|
||||||
|
|
||||||
void watchPoint();
|
void watchPoint();
|
||||||
|
void setRegisterValue(int nr, const QString &value);
|
||||||
|
|
||||||
void showStatusMessage(const QString &msg, int timeout = -1); // -1 forever
|
void showStatusMessage(const QString &msg, int timeout = -1); // -1 forever
|
||||||
|
|
||||||
|
@@ -78,12 +78,10 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
using namespace Debugger;
|
namespace Debugger {
|
||||||
using namespace Debugger::Internal;
|
namespace Internal {
|
||||||
using namespace Debugger::Constants;
|
using namespace Debugger::Constants;
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(Debugger::Internal::GdbMi);
|
|
||||||
|
|
||||||
//#define DEBUG_PENDING 1
|
//#define DEBUG_PENDING 1
|
||||||
//#define DEBUG_SUBITEM 1
|
//#define DEBUG_SUBITEM 1
|
||||||
|
|
||||||
@@ -1721,13 +1719,6 @@ void GdbEngine::handleAttach(const GdbResultRecord &, const QVariant &)
|
|||||||
if (supportsThreads())
|
if (supportsThreads())
|
||||||
postCommand(_("-thread-list-ids"), WatchUpdate, CB(handleStackListThreads), 0);
|
postCommand(_("-thread-list-ids"), WatchUpdate, CB(handleStackListThreads), 0);
|
||||||
|
|
||||||
//
|
|
||||||
// Disassembler
|
|
||||||
//
|
|
||||||
// XXX we have no data here ...
|
|
||||||
//m_address = data.findChild("frame").findChild("addr").data();
|
|
||||||
//qq->reloadDisassembler();
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Registers
|
// Registers
|
||||||
//
|
//
|
||||||
@@ -2583,6 +2574,20 @@ void GdbEngine::reloadRegisters()
|
|||||||
Discardable, CB(handleRegisterListValues));
|
Discardable, CB(handleRegisterListValues));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GdbEngine::setRegisterValue(int nr, const QString &value)
|
||||||
|
{
|
||||||
|
Register reg = qq->registerHandler()->registers().at(nr);
|
||||||
|
//qDebug() << "NOT IMPLEMENTED: CHANGE REGISTER " << nr << reg.name << ":"
|
||||||
|
// << value;
|
||||||
|
postCommand(_("-var-delete \"R@\""));
|
||||||
|
postCommand(_("-var-create \"R@\" * $%1").arg(reg.name));
|
||||||
|
postCommand(_("-var-assign \"R@\" %1").arg(value));
|
||||||
|
postCommand(_("-var-delete \"R@\""));
|
||||||
|
//postCommand(_("-data-list-register-values d"),
|
||||||
|
// Discardable, CB(handleRegisterListValues));
|
||||||
|
reloadRegisters();
|
||||||
|
}
|
||||||
|
|
||||||
void GdbEngine::handleRegisterListNames(const GdbResultRecord &record, const QVariant &)
|
void GdbEngine::handleRegisterListNames(const GdbResultRecord &record, const QVariant &)
|
||||||
{
|
{
|
||||||
if (record.resultClass != GdbResultDone)
|
if (record.resultClass != GdbResultDone)
|
||||||
@@ -3926,16 +3931,23 @@ void GdbEngine::handleWatchPoint(const GdbResultRecord &record, const QVariant &
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static QVariant agentCookie(void *agent)
|
|
||||||
|
struct MemoryAgentCookie
|
||||||
{
|
{
|
||||||
return QVariant(quint64(quintptr(agent)));
|
MemoryAgentCookie() : agent(0), address(0) {}
|
||||||
}
|
MemoryAgentCookie(MemoryViewAgent *agent_, quint64 address_)
|
||||||
|
: agent(agent_), address(address_)
|
||||||
|
{}
|
||||||
|
MemoryViewAgent *agent;
|
||||||
|
quint64 address;
|
||||||
|
};
|
||||||
|
|
||||||
void GdbEngine::fetchMemory(MemoryViewAgent *agent, quint64 addr, quint64 length)
|
void GdbEngine::fetchMemory(MemoryViewAgent *agent, quint64 addr, quint64 length)
|
||||||
{
|
{
|
||||||
//qDebug() << "GDB MEMORY FETCH" << addr << length;
|
//qDebug() << "GDB MEMORY FETCH" << agent << addr << length;
|
||||||
postCommand(_("-data-read-memory %1 x 1 1 %2").arg(addr).arg(length),
|
postCommand(_("-data-read-memory %1 x 1 1 %2").arg(addr).arg(length),
|
||||||
NeedsStop, CB(handleFetchMemory), agentCookie(agent));
|
NeedsStop, CB(handleFetchMemory),
|
||||||
|
QVariant::fromValue(MemoryAgentCookie(agent, addr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::handleFetchMemory(const GdbResultRecord &record,
|
void GdbEngine::handleFetchMemory(const GdbResultRecord &record,
|
||||||
@@ -3945,27 +3957,34 @@ void GdbEngine::handleFetchMemory(const GdbResultRecord &record,
|
|||||||
// next-row="0x08910c98",prev-row="0x08910c78",next-page="0x08910c98",
|
// next-row="0x08910c98",prev-row="0x08910c78",next-page="0x08910c98",
|
||||||
// prev-page="0x08910c78",memory=[{addr="0x08910c88",
|
// prev-page="0x08910c78",memory=[{addr="0x08910c88",
|
||||||
// data=["1","0","0","0","5","0","0","0","0","0","0","0","0","0","0","0"]}]
|
// data=["1","0","0","0","5","0","0","0","0","0","0","0","0","0","0","0"]}]
|
||||||
bool ok = true;
|
MemoryAgentCookie ac = cookie.value<MemoryAgentCookie>();
|
||||||
MemoryViewAgent *agent = (MemoryViewAgent *)cookie.toULongLong(&ok);
|
QTC_ASSERT(ac.agent, return);
|
||||||
QTC_ASSERT(ok, return);
|
|
||||||
QTC_ASSERT(agent, return);
|
|
||||||
QByteArray ba;
|
QByteArray ba;
|
||||||
GdbMi memory = record.data.findChild("memory");
|
GdbMi memory = record.data.findChild("memory");
|
||||||
QTC_ASSERT(memory.children().size() <= 1, return);
|
QTC_ASSERT(memory.children().size() <= 1, return);
|
||||||
|
if (memory.children().isEmpty())
|
||||||
|
return;
|
||||||
GdbMi memory0 = memory.children().at(0); // we asked for only one 'row'
|
GdbMi memory0 = memory.children().at(0); // we asked for only one 'row'
|
||||||
quint64 addr = memory0.findChild("addr").data().toULongLong(&ok, 0);
|
|
||||||
QTC_ASSERT(ok, return);
|
|
||||||
GdbMi data = memory0.findChild("data");
|
GdbMi data = memory0.findChild("data");
|
||||||
foreach (const GdbMi &child, data.children()) {
|
foreach (const GdbMi &child, data.children()) {
|
||||||
|
bool ok = true;
|
||||||
unsigned char c = child.data().toUInt(&ok, 0);
|
unsigned char c = child.data().toUInt(&ok, 0);
|
||||||
QTC_ASSERT(ok, return);
|
QTC_ASSERT(ok, return);
|
||||||
ba.append(c);
|
ba.append(c);
|
||||||
}
|
}
|
||||||
//qDebug() << "GDB READ MEMORY" << agent << addr << data.data() << ba.size();
|
ac.agent->addLazyData(ac.address, ba);
|
||||||
agent->addLazyData(addr, ba);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct DisassemblerAgentCookie
|
||||||
|
{
|
||||||
|
DisassemblerAgentCookie() : agent(0) {}
|
||||||
|
DisassemblerAgentCookie(DisassemblerViewAgent *agent_)
|
||||||
|
: agent(agent_)
|
||||||
|
{}
|
||||||
|
DisassemblerViewAgent *agent;
|
||||||
|
};
|
||||||
|
|
||||||
void GdbEngine::fetchDisassembler(DisassemblerViewAgent *agent,
|
void GdbEngine::fetchDisassembler(DisassemblerViewAgent *agent,
|
||||||
const StackFrame &frame)
|
const StackFrame &frame)
|
||||||
{
|
{
|
||||||
@@ -3975,7 +3994,8 @@ void GdbEngine::fetchDisassembler(DisassemblerViewAgent *agent,
|
|||||||
// Disassemble full function:
|
// Disassemble full function:
|
||||||
QString cmd = _("-data-disassemble -f %1 -l %2 -n -1 -- 1");
|
QString cmd = _("-data-disassemble -f %1 -l %2 -n -1 -- 1");
|
||||||
postCommand(cmd.arg(frame.file).arg(frame.line),
|
postCommand(cmd.arg(frame.file).arg(frame.line),
|
||||||
Discardable, CB(handleFetchDisassemblerByLine), agentCookie(agent));
|
Discardable, CB(handleFetchDisassemblerByLine),
|
||||||
|
QVariant::fromValue(DisassemblerAgentCookie(agent)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3991,10 +4011,12 @@ void GdbEngine::fetchDisassemblerByAddress(DisassemblerViewAgent *agent,
|
|||||||
// | [ -f filename -l linenum [ -n lines ] ] -- mode
|
// | [ -f filename -l linenum [ -n lines ] ] -- mode
|
||||||
if (useMixedMode)
|
if (useMixedMode)
|
||||||
postCommand(_("-data-disassemble -s %1 -e %2 -- 1").arg(start).arg(end),
|
postCommand(_("-data-disassemble -s %1 -e %2 -- 1").arg(start).arg(end),
|
||||||
Discardable, CB(handleFetchDisassemblerByAddress1), agentCookie(agent));
|
Discardable, CB(handleFetchDisassemblerByAddress1),
|
||||||
|
QVariant::fromValue(DisassemblerAgentCookie(agent)));
|
||||||
else
|
else
|
||||||
postCommand(_("-data-disassemble -s %1 -e %2 -- 0").arg(start).arg(end),
|
postCommand(_("-data-disassemble -s %1 -e %2 -- 0").arg(start).arg(end),
|
||||||
Discardable, CB(handleFetchDisassemblerByAddress0), agentCookie(agent));
|
Discardable, CB(handleFetchDisassemblerByAddress0),
|
||||||
|
QVariant::fromValue(DisassemblerAgentCookie(agent)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static QByteArray parseLine(const GdbMi &line)
|
static QByteArray parseLine(const GdbMi &line)
|
||||||
@@ -4060,37 +4082,35 @@ static QString parseDisassembler(const GdbMi &lines)
|
|||||||
void GdbEngine::handleFetchDisassemblerByLine(const GdbResultRecord &record,
|
void GdbEngine::handleFetchDisassemblerByLine(const GdbResultRecord &record,
|
||||||
const QVariant &cookie)
|
const QVariant &cookie)
|
||||||
{
|
{
|
||||||
bool ok = true;
|
DisassemblerAgentCookie ac = cookie.value<DisassemblerAgentCookie>();
|
||||||
DisassemblerViewAgent *agent = (DisassemblerViewAgent *)cookie.toULongLong(&ok);
|
QTC_ASSERT(ac.agent, return);
|
||||||
QTC_ASSERT(agent, return);
|
|
||||||
|
|
||||||
if (record.resultClass == GdbResultDone) {
|
if (record.resultClass == GdbResultDone) {
|
||||||
GdbMi lines = record.data.findChild("asm_insns");
|
GdbMi lines = record.data.findChild("asm_insns");
|
||||||
if (lines.children().isEmpty())
|
if (lines.children().isEmpty())
|
||||||
fetchDisassemblerByAddress(agent, true);
|
fetchDisassemblerByAddress(ac.agent, true);
|
||||||
else
|
else
|
||||||
agent->setContents(parseDisassembler(lines));
|
ac.agent->setContents(parseDisassembler(lines));
|
||||||
} else if (record.resultClass == GdbResultError) {
|
} else if (record.resultClass == GdbResultError) {
|
||||||
//536^error,msg="mi_cmd_disassemble: Invalid line number"
|
//536^error,msg="mi_cmd_disassemble: Invalid line number"
|
||||||
QByteArray msg = record.data.findChild("msg").data();
|
QByteArray msg = record.data.findChild("msg").data();
|
||||||
if (msg == "mi_cmd_disassemble: Invalid line number")
|
if (msg == "mi_cmd_disassemble: Invalid line number")
|
||||||
fetchDisassemblerByAddress(agent, true);
|
fetchDisassemblerByAddress(ac.agent, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::handleFetchDisassemblerByAddress1(const GdbResultRecord &record,
|
void GdbEngine::handleFetchDisassemblerByAddress1(const GdbResultRecord &record,
|
||||||
const QVariant &cookie)
|
const QVariant &cookie)
|
||||||
{
|
{
|
||||||
bool ok = true;
|
DisassemblerAgentCookie ac = cookie.value<DisassemblerAgentCookie>();
|
||||||
DisassemblerViewAgent *agent = (DisassemblerViewAgent *)cookie.toULongLong(&ok);
|
QTC_ASSERT(ac.agent, return);
|
||||||
QTC_ASSERT(agent, return);
|
|
||||||
|
|
||||||
if (record.resultClass == GdbResultDone) {
|
if (record.resultClass == GdbResultDone) {
|
||||||
GdbMi lines = record.data.findChild("asm_insns");
|
GdbMi lines = record.data.findChild("asm_insns");
|
||||||
if (lines.children().isEmpty())
|
if (lines.children().isEmpty())
|
||||||
fetchDisassemblerByAddress(agent, false);
|
fetchDisassemblerByAddress(ac.agent, false);
|
||||||
else
|
else
|
||||||
agent->setContents(parseDisassembler(lines));
|
ac.agent->setContents(parseDisassembler(lines));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4107,9 +4127,16 @@ void GdbEngine::handleFetchDisassemblerByAddress0(const GdbResultRecord &record,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
IDebuggerEngine *createGdbEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *opts)
|
IDebuggerEngine *createGdbEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *opts)
|
||||||
{
|
{
|
||||||
opts->push_back(new GdbOptionsPage);
|
opts->push_back(new GdbOptionsPage);
|
||||||
return new GdbEngine(parent);
|
return new GdbEngine(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Debugger
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(Debugger::Internal::MemoryAgentCookie);
|
||||||
|
Q_DECLARE_METATYPE(Debugger::Internal::DisassemblerAgentCookie);
|
||||||
|
Q_DECLARE_METATYPE(Debugger::Internal::GdbMi);
|
||||||
|
|
||||||
|
@@ -299,6 +299,7 @@ private:
|
|||||||
// Register specific stuff
|
// Register specific stuff
|
||||||
//
|
//
|
||||||
Q_SLOT void reloadRegisters();
|
Q_SLOT void reloadRegisters();
|
||||||
|
void setRegisterValue(int nr, const QString &value);
|
||||||
void handleRegisterListNames(const GdbResultRecord &record, const QVariant &);
|
void handleRegisterListNames(const GdbResultRecord &record, const QVariant &);
|
||||||
void handleRegisterListValues(const GdbResultRecord &record, const QVariant &);
|
void handleRegisterListValues(const GdbResultRecord &record, const QVariant &);
|
||||||
|
|
||||||
|
@@ -98,8 +98,9 @@ public:
|
|||||||
virtual void watchPoint(const QPoint &) {}
|
virtual void watchPoint(const QPoint &) {}
|
||||||
virtual void fetchMemory(MemoryViewAgent *, quint64 addr, quint64 length)
|
virtual void fetchMemory(MemoryViewAgent *, quint64 addr, quint64 length)
|
||||||
{ Q_UNUSED(addr); Q_UNUSED(length); }
|
{ Q_UNUSED(addr); Q_UNUSED(length); }
|
||||||
virtual void fetchDisassembler(DisassemblerViewAgent *, const StackFrame & /* frame */)
|
virtual void fetchDisassembler(DisassemblerViewAgent *, const StackFrame &) {}
|
||||||
{ }
|
virtual void setRegisterValue(int regnr, const QString &value)
|
||||||
|
{ Q_UNUSED(regnr); Q_UNUSED(value); }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -50,8 +50,9 @@ using namespace Debugger::Constants;
|
|||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
RegisterHandler::RegisterHandler(QObject *parent)
|
RegisterHandler::RegisterHandler(QObject *parent)
|
||||||
: QAbstractTableModel(parent), m_base(16)
|
: QAbstractTableModel(parent)
|
||||||
{
|
{
|
||||||
|
setNumberBase(16);
|
||||||
}
|
}
|
||||||
|
|
||||||
int RegisterHandler::rowCount(const QModelIndex &parent) const
|
int RegisterHandler::rowCount(const QModelIndex &parent) const
|
||||||
@@ -68,7 +69,7 @@ QVariant RegisterHandler::data(const QModelIndex &index, int role) const
|
|||||||
{
|
{
|
||||||
static const QVariant red = QColor(200, 0, 0);
|
static const QVariant red = QColor(200, 0, 0);
|
||||||
|
|
||||||
if (role == Qt::UserRole)
|
if (role == RegisterNumberBaseRole)
|
||||||
return m_base;
|
return m_base;
|
||||||
|
|
||||||
if (!index.isValid() || index.row() >= m_registers.size())
|
if (!index.isValid() || index.row() >= m_registers.size())
|
||||||
@@ -76,7 +77,7 @@ QVariant RegisterHandler::data(const QModelIndex &index, int role) const
|
|||||||
|
|
||||||
const Register ® = m_registers.at(index.row());
|
const Register ® = m_registers.at(index.row());
|
||||||
|
|
||||||
if (role == Qt::UserRole + 1) {
|
if (role == RegisterAddressRole) {
|
||||||
// return some address associated with the register
|
// return some address associated with the register
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
qulonglong value = reg.value.toULongLong(&ok, 0);
|
qulonglong value = reg.value.toULongLong(&ok, 0);
|
||||||
@@ -90,7 +91,8 @@ QVariant RegisterHandler::data(const QModelIndex &index, int role) const
|
|||||||
case 1: {
|
case 1: {
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
qulonglong value = reg.value.toULongLong(&ok, 0);
|
qulonglong value = reg.value.toULongLong(&ok, 0);
|
||||||
return ok ? padding + QString::number(value, m_base) + padding : reg.value;
|
QString res = ok ? QString::number(value, m_base) : reg.value;
|
||||||
|
return QString(m_strlen - res.size(), QLatin1Char(' ')) + res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,6 +118,26 @@ QVariant RegisterHandler::headerData(int section, Qt::Orientation orientation,
|
|||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags RegisterHandler::flags(const QModelIndex &idx) const
|
||||||
|
{
|
||||||
|
using namespace Qt;
|
||||||
|
|
||||||
|
if (!idx.isValid())
|
||||||
|
return ItemFlags();
|
||||||
|
|
||||||
|
static const ItemFlags notEditable =
|
||||||
|
ItemIsSelectable
|
||||||
|
| ItemIsDragEnabled
|
||||||
|
| ItemIsDropEnabled
|
||||||
|
| ItemIsEnabled;
|
||||||
|
|
||||||
|
static const ItemFlags editable = notEditable | ItemIsEditable;
|
||||||
|
|
||||||
|
if (idx.column() == 1)
|
||||||
|
return editable; // locals and watcher values are editable
|
||||||
|
return notEditable;
|
||||||
|
}
|
||||||
|
|
||||||
void RegisterHandler::removeAll()
|
void RegisterHandler::removeAll()
|
||||||
{
|
{
|
||||||
m_registers.clear();
|
m_registers.clear();
|
||||||
@@ -141,5 +163,6 @@ QList<Register> RegisterHandler::registers() const
|
|||||||
void RegisterHandler::setNumberBase(int base)
|
void RegisterHandler::setNumberBase(int base)
|
||||||
{
|
{
|
||||||
m_base = base;
|
m_base = base;
|
||||||
|
m_strlen = (base == 2 ? 64 : base == 8 ? 32 : base == 10 ? 26 : 16);
|
||||||
emit reset();
|
emit reset();
|
||||||
}
|
}
|
||||||
|
@@ -35,6 +35,12 @@
|
|||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
enum RegisterRole
|
||||||
|
{
|
||||||
|
RegisterNumberBaseRole = Qt::UserRole, // Currently used number base
|
||||||
|
RegisterAddressRole // Start value for opening memory view
|
||||||
|
};
|
||||||
|
|
||||||
class Register
|
class Register
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -68,9 +74,11 @@ private:
|
|||||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||||
QVariant headerData(int section, Qt::Orientation orientation,
|
QVariant headerData(int section, Qt::Orientation orientation,
|
||||||
int role = Qt::DisplayRole) const;
|
int role = Qt::DisplayRole) const;
|
||||||
|
Qt::ItemFlags flags(const QModelIndex &idx) const;
|
||||||
|
|
||||||
QList<Register> m_registers;
|
QList<Register> m_registers;
|
||||||
int m_base;
|
int m_base;
|
||||||
|
int m_strlen; // approximate width of an value in chars
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -28,11 +28,14 @@
|
|||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include "registerwindow.h"
|
#include "registerwindow.h"
|
||||||
|
#include "registerhandler.h"
|
||||||
|
|
||||||
#include "debuggeractions.h"
|
#include "debuggeractions.h"
|
||||||
#include "debuggeragents.h"
|
#include "debuggeragents.h"
|
||||||
#include "debuggerconstants.h"
|
#include "debuggerconstants.h"
|
||||||
|
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QtCore/QDir>
|
#include <QtCore/QDir>
|
||||||
#include <QtCore/QFileInfo>
|
#include <QtCore/QFileInfo>
|
||||||
@@ -40,13 +43,99 @@
|
|||||||
|
|
||||||
#include <QtGui/QAction>
|
#include <QtGui/QAction>
|
||||||
#include <QtGui/QHeaderView>
|
#include <QtGui/QHeaderView>
|
||||||
|
#include <QtGui/QItemDelegate>
|
||||||
|
#include <QtGui/QLineEdit>
|
||||||
#include <QtGui/QMenu>
|
#include <QtGui/QMenu>
|
||||||
|
#include <QtGui/QPainter>
|
||||||
#include <QtGui/QResizeEvent>
|
#include <QtGui/QResizeEvent>
|
||||||
#include <QtGui/QToolButton>
|
#include <QtGui/QToolButton>
|
||||||
|
|
||||||
|
|
||||||
using namespace Debugger::Internal;
|
namespace Debugger {
|
||||||
using namespace Debugger::Constants;
|
namespace Internal {
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// RegisterDelegate
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class RegisterDelegate : public QItemDelegate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RegisterDelegate(DebuggerManager *manager, QObject *parent)
|
||||||
|
: QItemDelegate(parent), m_manager(manager)
|
||||||
|
{}
|
||||||
|
|
||||||
|
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &,
|
||||||
|
const QModelIndex &) const
|
||||||
|
{
|
||||||
|
QLineEdit *lineEdit = new QLineEdit(parent);
|
||||||
|
lineEdit->setAlignment(Qt::AlignRight);
|
||||||
|
return lineEdit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setEditorData(QWidget *editor, const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
QLineEdit *lineEdit = qobject_cast<QLineEdit *>(editor);
|
||||||
|
QTC_ASSERT(lineEdit, return);
|
||||||
|
lineEdit->setText(index.model()->data(index, Qt::DisplayRole).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void setModelData(QWidget *editor, QAbstractItemModel *model,
|
||||||
|
const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(model);
|
||||||
|
//qDebug() << "SET MODEL DATA";
|
||||||
|
QLineEdit *lineEdit = qobject_cast<QLineEdit*>(editor);
|
||||||
|
QTC_ASSERT(lineEdit, return);
|
||||||
|
QString value = lineEdit->text();
|
||||||
|
//model->setData(index, value, Qt::EditRole);
|
||||||
|
if (index.column() == 1)
|
||||||
|
m_manager->setRegisterValue(index.row(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
|
||||||
|
const QModelIndex &) const
|
||||||
|
{
|
||||||
|
editor->setGeometry(option.rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||||
|
const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (index.column() == 1) {
|
||||||
|
// FIXME: performance? this changes only on real font changes.
|
||||||
|
QFontMetrics fm(option.font);
|
||||||
|
int charWidth = fm.width(QLatin1Char('x'));
|
||||||
|
for (int i = '1'; i <= '9'; ++i)
|
||||||
|
charWidth = qMax(charWidth, fm.width(QLatin1Char(i)));
|
||||||
|
for (int i = 'a'; i <= 'f'; ++i)
|
||||||
|
charWidth = qMax(charWidth, fm.width(QLatin1Char(i)));
|
||||||
|
QString str = index.model()->data(index, Qt::DisplayRole).toString();
|
||||||
|
int x = option.rect.x();
|
||||||
|
for (int i = 0; i < str.size(); ++i) {
|
||||||
|
QRect r = option.rect;
|
||||||
|
r.setX(x);
|
||||||
|
r.setWidth(charWidth);
|
||||||
|
x += charWidth;
|
||||||
|
painter->drawText(r, Qt::AlignHCenter, QString(str.at(i)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
QItemDelegate::paint(painter, option, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DebuggerManager *m_manager;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// RegisterWindow
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
RegisterWindow::RegisterWindow(DebuggerManager *manager)
|
RegisterWindow::RegisterWindow(DebuggerManager *manager)
|
||||||
: m_manager(manager), m_alwaysResizeColumnsToContents(true),
|
: m_manager(manager), m_alwaysResizeColumnsToContents(true),
|
||||||
@@ -57,6 +146,7 @@ RegisterWindow::RegisterWindow(DebuggerManager *manager)
|
|||||||
setSortingEnabled(true);
|
setSortingEnabled(true);
|
||||||
setAlternatingRowColors(act->isChecked());
|
setAlternatingRowColors(act->isChecked());
|
||||||
setRootIsDecorated(false);
|
setRootIsDecorated(false);
|
||||||
|
setItemDelegate(new RegisterDelegate(m_manager, this));
|
||||||
|
|
||||||
connect(act, SIGNAL(toggled(bool)),
|
connect(act, SIGNAL(toggled(bool)),
|
||||||
this, SLOT(setAlternatingRowColorsHelper(bool)));
|
this, SLOT(setAlternatingRowColorsHelper(bool)));
|
||||||
@@ -84,7 +174,7 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
|
|
||||||
QModelIndex idx = indexAt(ev->pos());
|
QModelIndex idx = indexAt(ev->pos());
|
||||||
QString address = model()->data(idx, Qt::UserRole + 1).toString();
|
QString address = model()->data(idx, RegisterAddressRole).toString();
|
||||||
QAction *actShowMemory = menu.addAction(QString());
|
QAction *actShowMemory = menu.addAction(QString());
|
||||||
if (address.isEmpty()) {
|
if (address.isEmpty()) {
|
||||||
actShowMemory->setText(tr("Open memory editor"));
|
actShowMemory->setText(tr("Open memory editor"));
|
||||||
@@ -94,7 +184,7 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
}
|
}
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
|
|
||||||
int base = model()->data(QModelIndex(), Qt::UserRole).toInt();
|
int base = model()->data(QModelIndex(), RegisterNumberBaseRole).toInt();
|
||||||
QAction *act16 = menu.addAction(tr("Hexadecimal"));
|
QAction *act16 = menu.addAction(tr("Hexadecimal"));
|
||||||
act16->setCheckable(true);
|
act16->setCheckable(true);
|
||||||
act16->setChecked(base == 16);
|
act16->setChecked(base == 16);
|
||||||
@@ -112,7 +202,7 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
menu.addAction(theDebuggerAction(SettingsDialog));
|
menu.addAction(theDebuggerAction(SettingsDialog));
|
||||||
|
|
||||||
QAction *act = menu.exec(ev->globalPos());
|
QAction *act = menu.exec(ev->globalPos());
|
||||||
|
|
||||||
if (act == actAdjust)
|
if (act == actAdjust)
|
||||||
resizeColumnsToContents();
|
resizeColumnsToContents();
|
||||||
else if (act == actAlwaysAdjust)
|
else if (act == actAlwaysAdjust)
|
||||||
@@ -162,4 +252,6 @@ void RegisterWindow::setModel(QAbstractItemModel *model)
|
|||||||
QTreeView::setModel(model);
|
QTreeView::setModel(model);
|
||||||
setAlwaysResizeColumnsToContents(true);
|
setAlwaysResizeColumnsToContents(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Debugger
|
||||||
|
Reference in New Issue
Block a user