From 6e40b38b6350fc6d833317b788a3bfbc4c3683b6 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 12 Dec 2020 23:42:13 -0800 Subject: [PATCH] Qt: Fix issues with I/O viewer not properly synchronizing state --- CHANGES | 1 + src/platform/qt/IOViewer.cpp | 40 ++++++++++++++++-------------------- src/platform/qt/IOViewer.h | 10 ++++----- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/CHANGES b/CHANGES index bd5edee2e..1274a5fce 100644 --- a/CHANGES +++ b/CHANGES @@ -80,6 +80,7 @@ Other fixes: - Qt: Pre-attach GDB stub when launching with -g (fixes mgba.io/i/1950) - Qt: Fix crash when editing shortcuts with none selected (fixes mgba.io/i/1964) - Qt: Fix crashing when no OpenGL context can be obtained + - Qt: Fix issues with I/O viewer not properly synchronizing state - SM83: Simplify register pair access on big endian - SM83: Disassemble STOP as one byte - Wii: Fix crash on unloading irregularly sized GBA ROMs diff --git a/src/platform/qt/IOViewer.cpp b/src/platform/qt/IOViewer.cpp index 572cb58a7..92dfd1814 100644 --- a/src/platform/qt/IOViewer.cpp +++ b/src/platform/qt/IOViewer.cpp @@ -1072,17 +1072,16 @@ IOViewer::IOViewer(std::shared_ptr controller, QWidget* parent) } void IOViewer::updateRegister() { - m_value = 0; - uint16_t value = 0; { CoreController::Interrupter interrupter(m_controller); - value = GBAView16(static_cast(m_controller->thread()->core->cpu), BASE_IO | m_register); + m_value = GBAView16(static_cast(m_controller->thread()->core->cpu), BASE_IO | m_register); } for (int i = 0; i < 16; ++i) { - m_b[i]->setChecked(value & (1 << i)); + QSignalBlocker blocker(m_b[i]); + m_b[i]->setChecked(m_value & (1 << i)); } - m_value = value; + m_ui.regValue->setText("0x" + QString("%1").arg(m_value, 4, 16, QChar('0')).toUpper()); emit valueChanged(); } @@ -1103,7 +1102,7 @@ void IOViewer::writeback() { updateRegister(); } -void IOViewer::selectRegister(unsigned address) { +void IOViewer::selectRegister(int address) { m_register = address; QGridLayout* box = static_cast(m_ui.regDescription->layout()); if (box) { @@ -1130,7 +1129,10 @@ void IOViewer::selectRegister(unsigned address) { check->setEnabled(!ri.readonly); box->addWidget(check, i, 1, Qt::AlignRight); connect(check, &QAbstractButton::toggled, m_b[ri.start], &QAbstractButton::setChecked); - connect(m_b[ri.start], &QAbstractButton::toggled, check, &QAbstractButton::setChecked); + connect(this, &IOViewer::valueChanged, check, [check, this, &ri] { + QSignalBlocker blocker(check); + check->setChecked(bool(m_value & (1 << ri.start))); + }); } else if (ri.items.empty()) { QSpinBox* sbox = new QSpinBox; sbox->setEnabled(!ri.readonly); @@ -1140,20 +1142,16 @@ void IOViewer::selectRegister(unsigned address) { connect(sbox, static_cast(&QSpinBox::valueChanged), [sbox, this, &ri](int v) { for (int o = 0; o < ri.size; ++o) { - bool signalsBlocked = m_b[o + ri.start]->blockSignals(true); + QSignalBlocker blocker(m_b[o + ri.start]); m_b[o + ri.start]->setChecked(v & (1 << o)); - m_b[o + ri.start]->blockSignals(signalsBlocked); } + bitFlipped(); }); - auto connection = connect(this, &IOViewer::valueChanged, [sbox, &ri, this]() { + connect(this, &IOViewer::valueChanged, sbox, [sbox, this, &ri]() { + QSignalBlocker blocker(sbox); int v = (m_value >> ri.start) & ((1 << ri.size) - 1); - bool signalsBlocked = sbox->blockSignals(true); sbox->setValue(v); - sbox->blockSignals(signalsBlocked); - }); - connect(sbox, &QObject::destroyed, [connection, this]() { - this->disconnect(connection); }); } else { QComboBox* cbox = new QComboBox; @@ -1170,24 +1168,22 @@ void IOViewer::selectRegister(unsigned address) { connect(cbox, static_cast(&QComboBox::currentIndexChanged), [cbox, this, &ri](int index) { unsigned v = cbox->itemData(index).toUInt(); for (int o = 0; o < ri.size; ++o) { - bool signalsBlocked = m_b[o + ri.start]->blockSignals(true); + QSignalBlocker blocker(m_b[o + ri.start]); m_b[o + ri.start]->setChecked(v & (1 << o)); - m_b[o + ri.start]->blockSignals(signalsBlocked); } + bitFlipped(); }); - auto connection = connect(this, &IOViewer::valueChanged, [cbox, this, &ri]() { + connect(this, &IOViewer::valueChanged, cbox, [cbox, this, &ri]() { + QSignalBlocker blocker(cbox); unsigned v = (m_value >> ri.start) & ((1 << ri.size) - 1); for (int i = 0; i < 1 << ri.size; ++i) { if (cbox->itemData(i) == v) { cbox->setCurrentIndex(i); + break; } } }); - connect(cbox, &QObject::destroyed, [connection, this]() { - this->disconnect(connection); - }); - } ++i; } diff --git a/src/platform/qt/IOViewer.h b/src/platform/qt/IOViewer.h index c1ae69c49..9a89092b0 100644 --- a/src/platform/qt/IOViewer.h +++ b/src/platform/qt/IOViewer.h @@ -21,19 +21,19 @@ Q_OBJECT public: struct RegisterItem { - RegisterItem(const QString& description, uint start, uint size = 1, bool readonly = false) + RegisterItem(const QString& description, uint start, int size = 1, bool readonly = false) : start(start) , size(size) , readonly(readonly) , description(description) {} - RegisterItem(const QString& description, uint start, uint size, QStringList items, bool readonly = false) + RegisterItem(const QString& description, uint start, int size, QStringList items, bool readonly = false) : start(start) , size(size) , readonly(readonly) , description(description) , items(items) {} uint start; - uint size; + int size; bool readonly; QString description; QStringList items; @@ -49,7 +49,7 @@ signals: public slots: void updateRegister(); - void selectRegister(unsigned address); + void selectRegister(int address); private slots: void buttonPressed(QAbstractButton* button); @@ -61,7 +61,7 @@ private: static QList s_registers; Ui::IOViewer m_ui; - unsigned m_register; + int m_register; uint16_t m_value; QCheckBox* m_b[16];