Qt: Memory viewer now supports editing decimal values directly (closes #1705)

This commit is contained in:
Vicki Pfau 2020-08-16 21:06:48 -07:00
parent ffbd0695bb
commit ff1e5f2de8
4 changed files with 191 additions and 4 deletions

View File

@ -62,6 +62,7 @@ Misc:
- Qt: Renderer can be changed while a game is running - Qt: Renderer can be changed while a game is running
- Qt: Add hex index to palette view - Qt: Add hex index to palette view
- Qt: Add transformation matrix info to sprite view - Qt: Add transformation matrix info to sprite view
- Qt: Memory viewer now supports editing decimal values directly (closes mgba.io/i/1705)
- Util: Reset vector size on deinit - Util: Reset vector size on deinit
0.8.3: (2020-08-03) 0.8.3: (2020-08-03)

View File

@ -13,6 +13,97 @@
using namespace QGBA; using namespace QGBA;
IntValidator::IntValidator(bool isSigned, QObject* parent)
: QValidator(parent)
, m_signed(isSigned)
{
}
QValidator::State IntValidator::validate(QString& input, int&) const {
if (input.isEmpty()) {
return QValidator::Intermediate;
}
if (input.size() == 1 && input[0] == '-') {
if (m_signed) {
return QValidator::Intermediate;
} else {
return QValidator::Invalid;
}
}
if (input[0].isSpace()) {
return QValidator::Invalid;
}
if (input[input.size() - 1].isSpace()) {
return QValidator::Invalid;
}
if (input.size() > 1 && input[0] == '0') {
return QValidator::Invalid;
}
bool ok = false;
qlonglong val = locale().toLongLong(input, &ok);
if (!ok) {
return QValidator::Invalid;
}
qlonglong hardmax;
qlonglong hardmin;
qlonglong max;
qlonglong min;
if (m_signed) {
switch (m_width) {
case 1:
hardmax = 999LL;
hardmin = -999LL;
max = 0x7FLL;
min = -0x80LL;
break;
case 2:
hardmax = 99999LL;
hardmin = -99999LL;
max = 0x7FFFLL;
min = -0x8000LL;
break;
case 4:
hardmax = 9999999999LL;
hardmin = -9999999999LL;
max = 0x7FFFFFFFLL;
min = -0x80000000LL;
break;
default:
return QValidator::Invalid;
}
} else {
hardmin = 0;
min = 0;
switch (m_width) {
case 1:
hardmax = 999LL;
max = 0xFFLL;
break;
case 2:
hardmax = 99999LL;
max = 0xFFFFLL;
break;
case 4:
hardmax = 9999999999LL;
max = 0xFFFFFFFFLL;
break;
default:
return QValidator::Invalid;
}
}
if (val < hardmin || val > hardmax) {
return QValidator::Invalid;
}
if (val < min || val > max) {
return QValidator::Intermediate;
}
return QValidator::Acceptable;
}
MemoryView::MemoryView(std::shared_ptr<CoreController> controller, QWidget* parent) MemoryView::MemoryView(std::shared_ptr<CoreController> controller, QWidget* parent)
: QWidget(parent) : QWidget(parent)
, m_controller(controller) , m_controller(controller)
@ -21,6 +112,9 @@ MemoryView::MemoryView(std::shared_ptr<CoreController> controller, QWidget* pare
m_ui.hexfield->setController(controller); m_ui.hexfield->setController(controller);
m_ui.sintVal->setValidator(&m_sintValidator);
m_ui.uintVal->setValidator(&m_uintValidator);
mCore* core = m_controller->thread()->core; mCore* core = m_controller->thread()->core;
const mCoreMemoryBlock* info; const mCoreMemoryBlock* info;
size_t nBlocks = core->listMemoryBlocks(core, &info); size_t nBlocks = core->listMemoryBlocks(core, &info);
@ -39,9 +133,21 @@ MemoryView::MemoryView(std::shared_ptr<CoreController> controller, QWidget* pare
} }
} }
connect(m_ui.width8, &QAbstractButton::clicked, [this]() { m_ui.hexfield->setAlignment(1); }); connect(m_ui.width8, &QAbstractButton::clicked, [this]() {
connect(m_ui.width16, &QAbstractButton::clicked, [this]() { m_ui.hexfield->setAlignment(2); }); m_ui.hexfield->setAlignment(1);
connect(m_ui.width32, &QAbstractButton::clicked, [this]() { m_ui.hexfield->setAlignment(4); }); m_sintValidator.setWidth(1);
m_uintValidator.setWidth(1);
});
connect(m_ui.width16, &QAbstractButton::clicked, [this]() {
m_ui.hexfield->setAlignment(2);
m_sintValidator.setWidth(2);
m_uintValidator.setWidth(2);
});
connect(m_ui.width32, &QAbstractButton::clicked, [this]() {
m_ui.hexfield->setAlignment(4);
m_sintValidator.setWidth(4);
m_uintValidator.setWidth(4);
});
connect(m_ui.setAddress, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), connect(m_ui.setAddress, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
this, static_cast<void (MemoryView::*)(uint32_t)>(&MemoryView::jumpToAddress)); this, static_cast<void (MemoryView::*)(uint32_t)>(&MemoryView::jumpToAddress));
connect(m_ui.hexfield, &MemoryModel::selectionChanged, this, &MemoryView::updateSelection); connect(m_ui.hexfield, &MemoryModel::selectionChanged, this, &MemoryView::updateSelection);
@ -60,6 +166,41 @@ MemoryView::MemoryView(std::shared_ptr<CoreController> controller, QWidget* pare
connect(m_ui.load, &QAbstractButton::clicked, m_ui.hexfield, &MemoryModel::load); connect(m_ui.load, &QAbstractButton::clicked, m_ui.hexfield, &MemoryModel::load);
connect(m_ui.loadTBL, &QAbstractButton::clicked, m_ui.hexfield, &MemoryModel::loadTBL); connect(m_ui.loadTBL, &QAbstractButton::clicked, m_ui.hexfield, &MemoryModel::loadTBL);
connect(m_ui.sintVal, &QLineEdit::returnPressed, this, [this]() {
int align = m_ui.hexfield->alignment();
mCore* core = m_controller->thread()->core;
int32_t value = m_ui.sintVal->text().toInt();
switch (align) {
case 1:
core->rawWrite8(core, m_selection.first, m_ui.segments->value(), value);
break;
case 2:
core->rawWrite16(core, m_selection.first, m_ui.segments->value(), value);
break;
case 4:
core->rawWrite32(core, m_selection.first, m_ui.segments->value(), value);
break;
}
update();
});
connect(m_ui.uintVal, &QLineEdit::returnPressed, this, [this]() {
int align = m_ui.hexfield->alignment();
mCore* core = m_controller->thread()->core;
uint32_t value = m_ui.uintVal->text().toUInt();
switch (align) {
case 1:
core->rawWrite8(core, m_selection.first, m_ui.segments->value(), value);
break;
case 2:
core->rawWrite16(core, m_selection.first, m_ui.segments->value(), value);
break;
case 4:
core->rawWrite32(core, m_selection.first, m_ui.segments->value(), value);
break;
}
update();
});
} }
void MemoryView::setIndex(int index) { void MemoryView::setIndex(int index) {
@ -116,7 +257,9 @@ void MemoryView::updateStatus() {
if (m_selection.first & (align - 1) || m_selection.second - m_selection.first != align) { if (m_selection.first & (align - 1) || m_selection.second - m_selection.first != align) {
m_ui.sintVal->clear(); m_ui.sintVal->clear();
m_ui.sintVal->setReadOnly(true);
m_ui.uintVal->clear(); m_ui.uintVal->clear();
m_ui.uintVal->setReadOnly(true);
return; return;
} }
union { union {
@ -144,6 +287,8 @@ void MemoryView::updateStatus() {
m_ui.uintVal->setText(QString::number(value.u32)); m_ui.uintVal->setText(QString::number(value.u32));
break; break;
} }
m_ui.sintVal->setReadOnly(false);
m_ui.uintVal->setReadOnly(false);
} }
void MemoryView::saveRange() { void MemoryView::saveRange() {
@ -153,4 +298,4 @@ void MemoryView::saveRange() {
memdump->setSegment(m_ui.segments->value()); memdump->setSegment(m_ui.segments->value());
memdump->setByteCount(m_selection.second - m_selection.first); memdump->setByteCount(m_selection.second - m_selection.first);
memdump->show(); memdump->show();
} }

View File

@ -5,6 +5,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#pragma once #pragma once
#include <QValidator>
#include "MemoryModel.h" #include "MemoryModel.h"
#include "ui_MemoryView.h" #include "ui_MemoryView.h"
@ -13,6 +15,20 @@ namespace QGBA {
class CoreController; class CoreController;
class IntValidator : public QValidator {
Q_OBJECT
public:
IntValidator(bool isSigned, QObject* parent = nullptr);
virtual QValidator::State validate(QString& input, int& pos) const override;
void setWidth(int bytes) { m_width = bytes; }
private:
int m_width = 1;
bool m_signed;
};
class MemoryView : public QWidget { class MemoryView : public QWidget {
Q_OBJECT Q_OBJECT
@ -32,6 +48,8 @@ private slots:
private: private:
Ui::MemoryView m_ui; Ui::MemoryView m_ui;
IntValidator m_sintValidator{true};
IntValidator m_uintValidator{false};
std::shared_ptr<CoreController> m_controller; std::shared_ptr<CoreController> m_controller;
QPair<uint32_t, uint32_t> m_region; QPair<uint32_t, uint32_t> m_region;

View File

@ -190,6 +190,9 @@
</item> </item>
<item> <item>
<widget class="QLineEdit" name="uintVal"> <widget class="QLineEdit" name="uintVal">
<property name="maxLength">
<number>10</number>
</property>
<property name="readOnly"> <property name="readOnly">
<bool>true</bool> <bool>true</bool>
</property> </property>
@ -208,6 +211,9 @@
</item> </item>
<item> <item>
<widget class="QLineEdit" name="sintVal"> <widget class="QLineEdit" name="sintVal">
<property name="maxLength">
<number>11</number>
</property>
<property name="readOnly"> <property name="readOnly">
<bool>true</bool> <bool>true</bool>
</property> </property>
@ -304,6 +310,23 @@
<container>1</container> <container>1</container>
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<tabstops>
<tabstop>regions</tabstop>
<tabstop>segments</tabstop>
<tabstop>setAddress</tabstop>
<tabstop>width8</tabstop>
<tabstop>width16</tabstop>
<tabstop>width32</tabstop>
<tabstop>sintVal</tabstop>
<tabstop>uintVal</tabstop>
<tabstop>stringVal</tabstop>
<tabstop>loadTBL</tabstop>
<tabstop>copy</tabstop>
<tabstop>paste</tabstop>
<tabstop>save</tabstop>
<tabstop>saveRange</tabstop>
<tabstop>load</tabstop>
</tabstops>
<resources/> <resources/>
<connections/> <connections/>
</ui> </ui>