Debugger: Replace QInputDialog with AsyncInputDialog

This commit is contained in:
chaoticgd
2026-02-03 20:07:32 -05:00
committed by Ty
parent a64431c7b5
commit 209e676e3a
6 changed files with 157 additions and 164 deletions
+37 -43
View File
@@ -3,6 +3,7 @@
#include "DisassemblyView.h"
#include "AsyncDialogs.h"
#include "Debugger/DebuggerWindow.h"
#include "Debugger/JsonValueWrapper.h"
#include "Debugger/Breakpoints/BreakpointModel.h"
@@ -18,7 +19,6 @@
#include <QtGui/QMouseEvent>
#include <QtWidgets/QMenu>
#include <QtGui/QClipboard>
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QMessageBox>
#include "SymbolTree/NewSymbolDialogs.h"
#include "common/StringUtil.h"
@@ -153,24 +153,23 @@ void DisassemblyView::contextAssembleInstruction()
}
DisassemblyLineInfo line;
bool ok;
m_disassemblyManager.getLine(m_selectedAddressStart, false, line);
QString instruction = QInputDialog::getText(this, tr("Assemble Instruction"), "",
QLineEdit::Normal, QString("%1 %2").arg(line.name.c_str()).arg(line.params.c_str()), &ok);
if (!ok)
return;
const QString title = tr("Assemble Instruction");
const QString text = QString("%1 %2").arg(line.name.c_str()).arg(line.params.c_str());
u32 encodedInstruction;
std::string errorText;
bool valid = MipsAssembleOpcode(instruction.toLocal8Bit().constData(), &cpu(), m_selectedAddressStart, encodedInstruction, errorText);
if (!valid)
{
QMessageBox::warning(this, tr("Assemble Error"), QString::fromStdString(errorText));
return;
}
AsyncDialogs::getText(this, title, "", text, [this](QString instruction) {
u32 encodedInstruction;
std::string errorText;
bool valid = MipsAssembleOpcode(instruction.toLocal8Bit().constData(), &cpu(), m_selectedAddressStart, encodedInstruction, errorText);
if (!valid)
{
QMessageBox::warning(this, tr("Assemble Error"), QString::fromStdString(errorText));
return;
}
setInstructions(m_selectedAddressStart, m_selectedAddressEnd, encodedInstruction);
setInstructions(m_selectedAddressStart, m_selectedAddressEnd, encodedInstruction);
});
}
void DisassemblyView::contextNoopInstruction()
@@ -249,22 +248,19 @@ void DisassemblyView::contextFollowBranch()
void DisassemblyView::contextGoToAddress()
{
bool ok;
const QString targetString = QInputDialog::getText(this, tr("Go To In Disassembly"), "",
QLineEdit::Normal, "", &ok);
const QString title = tr("Go To In Disassembly");
if (!ok)
return;
AsyncDialogs::getText(this, title, "", "", [this](QString expression) {
u64 address = 0;
std::string error;
if (!cpu().evaluateExpression(expression.toStdString().c_str(), address, error))
{
QMessageBox::warning(this, tr("Cannot Go To"), QString::fromStdString(error));
return;
}
u64 address = 0;
std::string error;
if (!cpu().evaluateExpression(targetString.toStdString().c_str(), address, error))
{
QMessageBox::warning(this, tr("Cannot Go To"), QString::fromStdString(error));
return;
}
gotoAddressAndSetFocus(static_cast<u32>(address) & ~3);
gotoAddressAndSetFocus(static_cast<u32>(address) & ~3);
});
}
void DisassemblyView::contextAddFunction()
@@ -304,28 +300,26 @@ void DisassemblyView::contextRemoveFunction()
void DisassemblyView::contextRenameFunction()
{
const FunctionInfo curFunc = cpu().GetSymbolGuardian().FunctionOverlappingAddress(m_selectedAddressStart);
if (!curFunc.address.valid())
{
QMessageBox::warning(this, tr("Rename Function Error"), tr("No function / symbol is currently selected."));
return;
}
QString oldName = QString::fromStdString(curFunc.name);
const QString title = tr("Rename Function");
const QString label = tr("Function name");
const QString oldName = QString::fromStdString(curFunc.name);
bool ok;
QString newName = QInputDialog::getText(this, tr("Rename Function"), tr("Function name"), QLineEdit::Normal, oldName, &ok);
if (!ok)
return;
AsyncDialogs::getText(this, title, label, oldName, [this, curFunc](QString newName) {
if (newName.isEmpty())
{
QMessageBox::warning(this, tr("Rename Function Error"), tr("Function name cannot be nothing."));
return;
}
if (newName.isEmpty())
{
QMessageBox::warning(this, tr("Rename Function Error"), tr("Function name cannot be nothing."));
return;
}
cpu().GetSymbolGuardian().ReadWrite([&](ccc::SymbolDatabase& database) {
database.functions.rename_symbol(curFunc.handle, newName.toStdString());
cpu().GetSymbolGuardian().ReadWrite([&](ccc::SymbolDatabase& database) {
database.functions.rename_symbol(curFunc.handle, newName.toStdString());
});
});
}
+15 -12
View File
@@ -3,6 +3,7 @@
#include "DockViews.h"
#include "AsyncDialogs.h"
#include "QtUtils.h"
#include "Debugger/DebuggerView.h"
#include "Debugger/DebuggerWindow.h"
@@ -17,7 +18,6 @@
#include <QtGui/QActionGroup>
#include <QtGui/QPalette>
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QMenu>
#include <QtWidgets/QStyleFactory>
@@ -176,19 +176,22 @@ void DockTabBar::openContextMenu(QPoint pos)
if (!widget)
return;
bool ok;
QString new_name = QInputDialog::getText(
this, tr("Rename Window"), tr("New name:"), QLineEdit::Normal, widget->displayNameWithoutSuffix(), &ok);
if (!ok)
return;
const QString title = tr("Rename Window");
const QString label = tr("New name:");
const QString text = widget->displayNameWithoutSuffix();
if (!widget->setCustomDisplayName(new_name))
{
QMessageBox::warning(this, tr("Invalid Name"), tr("The specified name is too long."));
return;
}
AsyncDialogs::getText(this, title, label, text, [this, widget = QPointer(widget)](QString name) {
if (!widget || !g_debugger_window)
return;
g_debugger_window->dockManager().updateDockWidgetTitles();
if (!widget->setCustomDisplayName(name))
{
QMessageBox::warning(this, tr("Invalid Name"), tr("The specified name is too long."));
return;
}
g_debugger_window->dockManager().updateDockWidgetTitles();
});
});
QAction* reset_name_action = menu->addAction(tr("Reset Name"));
+34 -40
View File
@@ -3,6 +3,7 @@
#include "MemoryView.h"
#include "AsyncDialogs.h"
#include "Debugger/JsonValueWrapper.h"
#include "QtHost.h"
@@ -12,7 +13,6 @@
#include <QtGui/QActionGroup>
#include <QtGui/QClipboard>
#include <QtGui/QMouseEvent>
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QMessageBox>
using namespace QtUtils;
@@ -305,36 +305,33 @@ bool MemoryViewTable::InsertFloatIntoSelectedHexView(DebugInterface& cpu)
std::memcpy(&currentFloatVal, &currentIntVal, sizeof(currentFloatVal));
const QString currentfloatStr = QString("%1").arg(QString::number(currentFloatVal, 'g'), 14).trimmed();
// Prompt user to enter a new float value
bool isValidInput = false;
QString newFloatStr = QInputDialog::getText(parent, tr("Input New Float"), "",
QLineEdit::Normal, currentfloatStr, &isValidInput);
if (!isValidInput)
return false;
const QString title = tr("Input New Float");
// Convert string into float value
bool isValidFloat = false;
const float newFloatVal = newFloatStr.toFloat(&isValidFloat);
if (!isValidFloat)
{
QMessageBox::warning(parent, tr("Input Error"), tr("Invalid float value"));
return false;
}
AsyncDialogs::getText(parent, title, "", currentfloatStr, [this, &cpu](QString newFloatStr) {
// Convert string into float value
bool isValidFloat = false;
const float newFloatVal = newFloatStr.toFloat(&isValidFloat);
if (!isValidFloat)
{
QMessageBox::warning(parent, tr("Input Error"), tr("Invalid float value"));
return;
}
// Write new float value back to memory
u32 newIntVal = 0;
std::memcpy(&newIntVal, &newFloatVal, sizeof(newIntVal));
newIntVal = convertEndian(newIntVal);
// Write new float value back to memory
u32 newIntVal = 0;
std::memcpy(&newIntVal, &newFloatVal, sizeof(newIntVal));
newIntVal = convertEndian(newIntVal);
const QPointer<MemoryViewTable> table(this);
Host::RunOnCPUThread([table, address = selectedAddress, &cpu, val = newIntVal] {
cpu.write32(address, val);
const QPointer<MemoryViewTable> table(this);
Host::RunOnCPUThread([table, address = selectedAddress, &cpu, val = newIntVal] {
cpu.write32(address, val);
QtHost::RunOnUIThread([table] {
if (!table)
return;
QtHost::RunOnUIThread([table] {
if (!table)
return;
table->parent->update();
table->parent->update();
});
});
});
@@ -899,22 +896,19 @@ void MemoryView::contextPaste()
void MemoryView::contextGoToAddress()
{
bool ok;
QString targetString = QInputDialog::getText(this, tr("Go To In Memory View"), "",
QLineEdit::Normal, "", &ok);
const QString title = tr("Go To In Memory View");
if (!ok)
return;
AsyncDialogs::getText(this, title, "", "", [this](QString expression) {
u64 address = 0;
std::string error;
if (!cpu().evaluateExpression(expression.toStdString().c_str(), address, error))
{
QMessageBox::warning(this, tr("Cannot Go To"), QString::fromStdString(error));
return;
}
u64 address = 0;
std::string error;
if (!cpu().evaluateExpression(targetString.toStdString().c_str(), address, error))
{
QMessageBox::warning(this, tr("Cannot Go To"), QString::fromStdString(error));
return;
}
gotoAddress(static_cast<u32>(address));
gotoAddress(static_cast<u32>(address));
});
}
void MemoryView::contextFollowAddress()
+60 -51
View File
@@ -3,15 +3,15 @@
#include "RegisterView.h"
#include "AsyncDialogs.h"
#include "QtUtils.h"
#include "Debugger/JsonValueWrapper.h"
#include "QtUtils.h"
#include <QtGui/QMouseEvent>
#include <QtWidgets/QTabBar>
#include <QtWidgets/QStylePainter>
#include <QtWidgets/QStyleOptionTab>
#include <QtGui/QClipboard>
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QProxyStyle>
#include <QtWidgets/QMessageBox>
@@ -351,12 +351,11 @@ void RegisterView::contextCopySegment()
QApplication::clipboard()->setText(FilledQStringFromValue(val._u32[3 - m_selected128Field], 16));
}
bool RegisterView::contextFetchNewValue(u64& out, u64 currentValue, bool segment)
void RegisterView::fetchNewValue(u64 currentValue, bool segment, std::function<void(u64)> callback)
{
const int categoryIndex = ui.registerTabs->currentIndex();
const bool floatingPoint = CAT_SHOW_FLOAT && segment;
const int regSize = cpu().getRegisterSize(categoryIndex);
bool ok = false;
QString existingValue("%1");
@@ -366,79 +365,89 @@ bool RegisterView::contextFetchNewValue(u64& out, u64 currentValue, bool segment
existingValue = existingValue.arg(std::bit_cast<float>((u32)currentValue));
//: Changing the value in a CPU register (e.g. "Change t0")
QString input = QInputDialog::getText(this, tr("Change %1").arg(cpu().getRegisterName(categoryIndex, m_selectedRow)), "",
QLineEdit::Normal, existingValue, &ok);
const QString title = tr("Change %1").arg(cpu().getRegisterName(categoryIndex, m_selectedRow));
if (!ok)
return false;
if (!floatingPoint) // Get input as hexadecimal
{
out = input.toULongLong(&ok, 16);
if (!ok)
AsyncDialogs::getText(this, title, "", existingValue, [this, callback, floatingPoint](QString input) {
u64 value;
if (!floatingPoint) // Get input as hexadecimal
{
QMessageBox::warning(this, tr("Invalid register value"), tr("Invalid hexadecimal register value."));
return false;
bool ok;
value = input.toULongLong(&ok, 16);
if (!ok)
{
QMessageBox::warning(this, tr("Invalid register value"), tr("Invalid hexadecimal register value."));
return;
}
}
}
else
{
out = std::bit_cast<u32>(input.toFloat(&ok));
if (!ok)
else
{
QMessageBox::warning(this, tr("Invalid register value"), tr("Invalid floating-point register value."));
return false;
bool ok;
value = std::bit_cast<u32>(input.toFloat(&ok));
if (!ok)
{
QMessageBox::warning(this, tr("Invalid register value"), tr("Invalid floating-point register value."));
return;
}
}
}
return true;
callback(value);
});
}
void RegisterView::contextChangeValue()
{
const int categoryIndex = ui.registerTabs->currentIndex();
u64 newVal;
if (contextFetchNewValue(newVal, cpu().getRegister(categoryIndex, m_selectedRow).lo))
{
cpu().setRegister(categoryIndex, m_selectedRow, u128::From64(newVal));
const int category_index = ui.registerTabs->currentIndex();
const s32 row = m_selectedRow;
const u32 old_value = cpu().getRegister(category_index, row).lo;
fetchNewValue(old_value, false, [this, category_index, row](u64 input) {
cpu().setRegister(category_index, row, u128::From64(input));
DebuggerView::broadcastEvent(DebuggerEvents::VMUpdate());
}
});
}
void RegisterView::contextChangeTop()
{
u64 newVal;
u128 oldVal = cpu().getRegister(ui.registerTabs->currentIndex(), m_selectedRow);
if (contextFetchNewValue(newVal, oldVal.hi))
{
oldVal.hi = newVal;
cpu().setRegister(ui.registerTabs->currentIndex(), m_selectedRow, oldVal);
const int category_index = ui.registerTabs->currentIndex();
const s32 row = m_selectedRow;
const u128 old_value = cpu().getRegister(category_index, row);
fetchNewValue(old_value.hi, false, [this, category_index, row, old_value](u32 input) {
u128 new_value = old_value;
new_value.hi = input;
cpu().setRegister(category_index, row, new_value);
DebuggerView::broadcastEvent(DebuggerEvents::VMUpdate());
}
});
}
void RegisterView::contextChangeBottom()
{
u64 newVal;
u128 oldVal = cpu().getRegister(ui.registerTabs->currentIndex(), m_selectedRow);
if (contextFetchNewValue(newVal, oldVal.lo))
{
oldVal.lo = newVal;
cpu().setRegister(ui.registerTabs->currentIndex(), m_selectedRow, oldVal);
const int category_index = ui.registerTabs->currentIndex();
const s32 row = m_selectedRow;
const u128 old_value = cpu().getRegister(category_index, row);
fetchNewValue(old_value.lo, false, [this, category_index, row, old_value](u32 input) {
u128 new_value = old_value;
new_value.lo = input;
cpu().setRegister(category_index, row, new_value);
DebuggerView::broadcastEvent(DebuggerEvents::VMUpdate());
}
});
}
void RegisterView::contextChangeSegment()
{
u64 newVal;
u128 oldVal = cpu().getRegister(ui.registerTabs->currentIndex(), m_selectedRow);
if (contextFetchNewValue(newVal, oldVal._u32[3 - m_selected128Field], true))
{
oldVal._u32[3 - m_selected128Field] = (u32)newVal;
cpu().setRegister(ui.registerTabs->currentIndex(), m_selectedRow, oldVal);
const int category_index = ui.registerTabs->currentIndex();
const s32 row = m_selectedRow;
const s32 field = m_selected128Field;
const u128 old_value = cpu().getRegister(category_index, row);
const u32 segment = old_value._u32[3 - field];
fetchNewValue(segment, false, [this, category_index, row, field, old_value](u32 input) {
u128 new_value = old_value;
new_value._u32[3 - field] = input;
cpu().setRegister(category_index, row, new_value);
DebuggerView::broadcastEvent(DebuggerEvents::VMUpdate());
}
});
}
std::optional<DebuggerEvents::GoToAddress> RegisterView::contextCreateGotoEvent()
+1 -2
View File
@@ -49,8 +49,7 @@ public slots:
private:
Ui::RegisterView ui;
// Returns true on success
bool contextFetchNewValue(u64& out, u64 currentValue, bool segment = false);
void fetchNewValue(u64 currentValue, bool segment, std::function<void(u64)> callback);
// Used for the height offset the tab bar creates
// because we share a widget
@@ -3,13 +3,13 @@
#include "SymbolTreeViews.h"
#include "AsyncDialogs.h"
#include "Debugger/JsonValueWrapper.h"
#include "Debugger/SymbolTree/NewSymbolDialogs.h"
#include "Debugger/SymbolTree/SymbolTreeDelegates.h"
#include <QtGui/QActionGroup>
#include <QtGui/QClipboard>
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QMenu>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QScrollBar>
@@ -701,13 +701,10 @@ void SymbolTreeView::onRenameSymbol()
text = QString::fromStdString(symbol->name());
});
bool ok;
std::string name = QInputDialog::getText(this, title, label, QLineEdit::Normal, text, &ok).toStdString();
if (!ok)
return;
cpu().GetSymbolGuardian().ReadWrite([&](ccc::SymbolDatabase& database) {
node->symbol.rename_symbol(name, database);
AsyncDialogs::getText(this, title, label, text, [this, handle = node->symbol](QString new_name) {
cpu().GetSymbolGuardian().ReadWrite([&](ccc::SymbolDatabase& database) {
handle.rename_symbol(new_name.toStdString(), database);
});
});
}
@@ -741,14 +738,11 @@ void SymbolTreeView::onChangeTypeTemporarily()
return;
}
bool ok;
QString type_string = QInputDialog::getText(this, title, label, QLineEdit::Normal, *old_type, &ok);
if (!ok)
return;
std::optional<QString> error_message = m_model->changeTypeTemporarily(index, type_string.toStdString());
if (error_message.has_value() && !error_message->isEmpty())
QMessageBox::warning(this, tr("Cannot Change Type"), *error_message);
AsyncDialogs::getText(this, title, label, *old_type, [this, index](QString type_string) {
std::optional<QString> error_message = m_model->changeTypeTemporarily(index, type_string.toStdString());
if (error_message.has_value() && !error_message->isEmpty())
QMessageBox::warning(this, tr("Cannot Change Type"), *error_message);
});
}
void SymbolTreeView::onTreeViewClicked(const QModelIndex& index)