mirror of https://github.com/mgba-emu/mgba.git
Qt: Memory view selection
This commit is contained in:
parent
21542034d3
commit
ebece20a43
|
@ -24,6 +24,8 @@ MemoryModel::MemoryModel(QWidget* parent)
|
|||
, m_cpu(nullptr)
|
||||
, m_top(0)
|
||||
, m_align(1)
|
||||
, m_selection(0, 0)
|
||||
, m_selectionAnchor(0)
|
||||
{
|
||||
m_font.setFamily("Source Code Pro");
|
||||
m_font.setStyleHint(QFont::Monospace);
|
||||
|
@ -50,7 +52,8 @@ MemoryModel::MemoryModel(QWidget* parent)
|
|||
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
m_margins = QMargins(metrics.width("0FFFFFF0 ") + 4, m_cellHeight + 1, metrics.width(" AAAAAAAAAAAAAAAA") + 3, 0);
|
||||
m_margins = QMargins(metrics.width("0FFFFFF0 ") + 3, m_cellHeight + 1, metrics.width(" AAAAAAAAAAAAAAAA") + 3, 0);
|
||||
m_cellSize = QSizeF((viewport()->size().width() - (m_margins.left() + m_margins.right())) / 16.0, m_cellHeight);
|
||||
|
||||
connect(verticalScrollBar(), &QSlider::sliderMoved, [this](int position) {
|
||||
m_top = position;
|
||||
|
@ -104,6 +107,7 @@ void MemoryModel::jumpToAddress(uint32_t address) {
|
|||
}
|
||||
|
||||
void MemoryModel::resizeEvent(QResizeEvent*) {
|
||||
m_cellSize = QSizeF((viewport()->size().width() - (m_margins.left() + m_margins.right())) / 16.0, m_cellHeight);
|
||||
verticalScrollBar()->setRange(0, (m_size >> 4) + 1 - viewport()->size().height() / m_cellHeight);
|
||||
boundsCheck();
|
||||
}
|
||||
|
@ -112,12 +116,11 @@ void MemoryModel::paintEvent(QPaintEvent* event) {
|
|||
QPainter painter(viewport());
|
||||
painter.setFont(m_font);
|
||||
QChar c0('0');
|
||||
QSizeF cellSize = QSizeF((viewport()->size().width() - (m_margins.left() + m_margins.right())) / 16.f, m_cellHeight);
|
||||
QSizeF letterSize = QSizeF(m_letterWidth, m_cellHeight);
|
||||
painter.drawStaticText(QPointF((m_margins.left() - m_regionName.size().width() - 1) / 2.0, 0), m_regionName);
|
||||
painter.drawText(QRect(QPoint(viewport()->size().width() - m_margins.right(), 0), QSize(m_margins.right(), m_margins.top())), Qt::AlignHCenter, tr("ASCII"));
|
||||
for (int x = 0; x < 16; ++x) {
|
||||
painter.drawText(QRectF(QPointF(cellSize.width() * x + m_margins.left(), 0), cellSize), Qt::AlignHCenter, QString::number(x, 16).toUpper());
|
||||
painter.drawText(QRectF(QPointF(m_cellSize.width() * x + m_margins.left(), 0), m_cellSize), Qt::AlignHCenter, QString::number(x, 16).toUpper());
|
||||
}
|
||||
int height = (viewport()->size().height() - m_cellHeight) / m_cellHeight;
|
||||
for (int y = 0; y < height; ++y) {
|
||||
|
@ -127,25 +130,37 @@ void MemoryModel::paintEvent(QPaintEvent* event) {
|
|||
switch (m_align) {
|
||||
case 2:
|
||||
for (int x = 0; x < 16; x += 2) {
|
||||
uint16_t b = m_cpu->memory.load16(m_cpu, (y + m_top) * 16 + x + m_base, nullptr);
|
||||
painter.drawStaticText(QPointF(cellSize.width() * (x + 1.0) - 2 * m_letterWidth + m_margins.left(), yp), m_staticNumbers[(b >> 8) & 0xFF]);
|
||||
painter.drawStaticText(QPointF(cellSize.width() * (x + 1.0) + m_margins.left(), yp), m_staticNumbers[b & 0xFF]);
|
||||
uint32_t address = (y + m_top) * 16 + x + m_base;
|
||||
if (isInSelection(address)) {
|
||||
painter.fillRect(QRectF(QPointF(m_cellSize.width() * x + m_margins.left(), yp), QSizeF(m_cellSize.width() * 2, m_cellSize.height())), Qt::lightGray);
|
||||
}
|
||||
uint16_t b = m_cpu->memory.load16(m_cpu, address, nullptr);
|
||||
painter.drawStaticText(QPointF(m_cellSize.width() * (x + 1.0) - 2 * m_letterWidth + m_margins.left(), yp), m_staticNumbers[(b >> 8) & 0xFF]);
|
||||
painter.drawStaticText(QPointF(m_cellSize.width() * (x + 1.0) + m_margins.left(), yp), m_staticNumbers[b & 0xFF]);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
for (int x = 0; x < 16; x += 4) {
|
||||
uint32_t b = m_cpu->memory.load32(m_cpu, (y + m_top) * 16 + x + m_base, nullptr);
|
||||
painter.drawStaticText(QPointF(cellSize.width() * (x + 2.0) - 4 * m_letterWidth + m_margins.left(), yp), m_staticNumbers[(b >> 24) & 0xFF]);
|
||||
painter.drawStaticText(QPointF(cellSize.width() * (x + 2.0) - 2 * m_letterWidth + m_margins.left(), yp), m_staticNumbers[(b >> 16) & 0xFF]);
|
||||
painter.drawStaticText(QPointF(cellSize.width() * (x + 2.0) + m_margins.left(), yp), m_staticNumbers[(b >> 8) & 0xFF]);
|
||||
painter.drawStaticText(QPointF(cellSize.width() * (x + 2.0) + 2 * m_letterWidth + m_margins.left(), yp), m_staticNumbers[b & 0xFF]);
|
||||
uint32_t address = (y + m_top) * 16 + x + m_base;
|
||||
if (isInSelection(address)) {
|
||||
painter.fillRect(QRectF(QPointF(m_cellSize.width() * x + m_margins.left(), yp), QSizeF(m_cellSize.width() * 4, m_cellSize.height())), Qt::lightGray);
|
||||
}
|
||||
uint32_t b = m_cpu->memory.load32(m_cpu, address, nullptr);
|
||||
painter.drawStaticText(QPointF(m_cellSize.width() * (x + 2.0) - 4 * m_letterWidth + m_margins.left(), yp), m_staticNumbers[(b >> 24) & 0xFF]);
|
||||
painter.drawStaticText(QPointF(m_cellSize.width() * (x + 2.0) - 2 * m_letterWidth + m_margins.left(), yp), m_staticNumbers[(b >> 16) & 0xFF]);
|
||||
painter.drawStaticText(QPointF(m_cellSize.width() * (x + 2.0) + m_margins.left(), yp), m_staticNumbers[(b >> 8) & 0xFF]);
|
||||
painter.drawStaticText(QPointF(m_cellSize.width() * (x + 2.0) + 2 * m_letterWidth + m_margins.left(), yp), m_staticNumbers[b & 0xFF]);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
for (int x = 0; x < 16; ++x) {
|
||||
uint8_t b = m_cpu->memory.load8(m_cpu, (y + m_top) * 16 + x + m_base, nullptr);
|
||||
painter.drawStaticText(QPointF(cellSize.width() * (x + 0.5) - m_letterWidth + m_margins.left(), yp), m_staticNumbers[b]);
|
||||
uint32_t address = (y + m_top) * 16 + x + m_base;
|
||||
if (isInSelection(address)) {
|
||||
painter.fillRect(QRectF(QPointF(m_cellSize.width() * x + m_margins.left(), yp), m_cellSize), Qt::lightGray);
|
||||
}
|
||||
uint8_t b = m_cpu->memory.load8(m_cpu, address, nullptr);
|
||||
painter.drawStaticText(QPointF(m_cellSize.width() * (x + 0.5) - m_letterWidth + m_margins.left(), yp), m_staticNumbers[b]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -154,7 +169,7 @@ void MemoryModel::paintEvent(QPaintEvent* event) {
|
|||
painter.drawStaticText(QPointF(viewport()->size().width() - (16 - x) * m_margins.right() / 17.0 - m_letterWidth * 0.5, yp), b < 0x80 ? m_staticAscii[b] : m_staticAscii[0]);
|
||||
}
|
||||
}
|
||||
painter.drawLine(m_margins.left() - 2, 0, m_margins.left() - 2, viewport()->size().height());
|
||||
painter.drawLine(m_margins.left(), 0, m_margins.left(), viewport()->size().height());
|
||||
painter.drawLine(viewport()->size().width() - m_margins.right(), 0, viewport()->size().width() - m_margins.right(), viewport()->size().height());
|
||||
painter.drawLine(0, m_margins.top(), viewport()->size().width(), m_margins.top());
|
||||
}
|
||||
|
@ -167,6 +182,34 @@ void MemoryModel::wheelEvent(QWheelEvent* event) {
|
|||
update();
|
||||
}
|
||||
|
||||
void MemoryModel::mousePressEvent(QMouseEvent* event) {
|
||||
if (event->x() < m_margins.left() || event->y() < m_margins.top() || event->x() > size().width() - m_margins.right()) {
|
||||
m_selection = qMakePair(0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
QPoint position(event->pos() - QPoint(m_margins.left(), m_margins.top()));
|
||||
uint32_t address = int(position.x() / m_cellSize.width()) + (int(position.y() / m_cellSize.height()) + m_top) * 16 + m_base;
|
||||
m_selectionAnchor = address & ~(m_align - 1);
|
||||
m_selection = qMakePair(m_selectionAnchor, m_selectionAnchor + m_align);
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
void MemoryModel::mouseMoveEvent(QMouseEvent* event) {
|
||||
if (event->x() < m_margins.left() || event->y() < m_margins.top() || event->x() > size().width() - m_margins.right()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QPoint position(event->pos() - QPoint(m_margins.left(), m_margins.top()));
|
||||
uint32_t address = int(position.x() / m_cellSize.width()) + (int(position.y() / m_cellSize.height()) + m_top) * 16 + m_base;
|
||||
if ((address & ~(m_align - 1)) < m_selectionAnchor) {
|
||||
m_selection = qMakePair(address & ~(m_align - 1), m_selectionAnchor + m_align);
|
||||
} else {
|
||||
m_selection = qMakePair(m_selectionAnchor, (address & ~(m_align - 1)) + m_align);
|
||||
}
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
void MemoryModel::boundsCheck() {
|
||||
if (m_top < 0) {
|
||||
m_top = 0;
|
||||
|
@ -174,3 +217,16 @@ void MemoryModel::boundsCheck() {
|
|||
m_top = (m_size >> 4) + 1 - viewport()->size().height() / m_cellHeight;
|
||||
}
|
||||
}
|
||||
|
||||
bool MemoryModel::isInSelection(uint32_t address) {
|
||||
if (m_selection.first == m_selection.second) {
|
||||
return false;
|
||||
}
|
||||
if (m_selection.second <= (address | (m_align - 1))) {
|
||||
return false;
|
||||
}
|
||||
if (m_selection.first <= (address & ~(m_align - 1))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -37,10 +37,14 @@ protected:
|
|||
void resizeEvent(QResizeEvent*) override;
|
||||
void paintEvent(QPaintEvent*) override;
|
||||
void wheelEvent(QWheelEvent*) override;
|
||||
void mousePressEvent(QMouseEvent*) override;
|
||||
void mouseMoveEvent(QMouseEvent*) override;
|
||||
|
||||
private:
|
||||
void boundsCheck();
|
||||
|
||||
bool isInSelection(uint32_t address);
|
||||
|
||||
ARMCore* m_cpu;
|
||||
QFont m_font;
|
||||
int m_cellHeight;
|
||||
|
@ -53,6 +57,9 @@ private:
|
|||
QVector<QStaticText> m_staticNumbers;
|
||||
QVector<QStaticText> m_staticAscii;
|
||||
QStaticText m_regionName;
|
||||
QSizeF m_cellSize;
|
||||
QPair<uint32_t, uint32_t> m_selection;
|
||||
uint32_t m_selectionAnchor;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue