diff --git a/rpcs3/rpcs3qt/debugger_frame.cpp b/rpcs3/rpcs3qt/debugger_frame.cpp index 193883e8ad..6c542258e0 100644 --- a/rpcs3/rpcs3qt/debugger_frame.cpp +++ b/rpcs3/rpcs3qt/debugger_frame.cpp @@ -859,6 +859,7 @@ void debugger_frame::UpdateUnitList() { if (m_reg_editor) m_reg_editor->close(); if (m_inst_editor) m_inst_editor->close(); + if (m_goto_dialog) m_goto_dialog->close(); } if (emu_state == system_state::stopped) @@ -1008,9 +1009,16 @@ void debugger_frame::WritePanels() void debugger_frame::ShowGotoAddressDialog() { - QDialog* dlg = new QDialog(this); - dlg->setWindowTitle(tr("Go To Address")); - dlg->setModal(true); + if (m_goto_dialog) + { + m_goto_dialog->move(QCursor::pos()); + m_goto_dialog->show(); + m_goto_dialog->setFocus(); + return; + } + + m_goto_dialog = new QDialog(this); + m_goto_dialog->setWindowTitle(tr("Go To Address")); // Panels QVBoxLayout* vbox_panel(new QVBoxLayout()); @@ -1018,7 +1026,7 @@ void debugger_frame::ShowGotoAddressDialog() QHBoxLayout* hbox_button_panel(new QHBoxLayout()); // Address expression input - QLineEdit* expression_input(new QLineEdit(dlg)); + QLineEdit* expression_input(new QLineEdit(m_goto_dialog)); expression_input->setFont(m_mono); expression_input->setMaxLength(18); @@ -1044,9 +1052,10 @@ void debugger_frame::ShowGotoAddressDialog() vbox_panel->addSpacing(8); vbox_panel->addLayout(hbox_button_panel); - dlg->setLayout(vbox_panel); + m_goto_dialog->setLayout(vbox_panel); - const auto cpu = get_cpu(); + const auto cpu_check = make_check_cpu(get_cpu()); + const auto cpu = cpu_check(); const QFont font = expression_input->font(); // -1 from get_pc() turns into 0 @@ -1054,18 +1063,35 @@ void debugger_frame::ShowGotoAddressDialog() expression_input->setPlaceholderText(QString("0x%1").arg(pc, 16, 16, QChar('0'))); expression_input->setFixedWidth(gui::utils::get_label_width(expression_input->placeholderText(), &font)); - connect(button_ok, &QAbstractButton::clicked, dlg, &QDialog::accept); - connect(button_cancel, &QAbstractButton::clicked, dlg, &QDialog::reject); + connect(button_ok, &QAbstractButton::clicked, m_goto_dialog, &QDialog::accept); + connect(button_cancel, &QAbstractButton::clicked, m_goto_dialog, &QDialog::reject); - dlg->move(QCursor::pos()); + m_goto_dialog->move(QCursor::pos()); + m_goto_dialog->setAttribute(Qt::WA_DeleteOnClose); - if (dlg->exec() == QDialog::Accepted) + connect(m_goto_dialog, &QDialog::finished, this, [this, cpu, cpu_check, expression_input](int result) { - const u32 address = EvaluateExpression(expression_input->text()); - m_debugger_list->ShowAddress(address, true); - } + // Check if the thread has not been destroyed and is still the focused since + // This also works if no thread is selected and has been selected before + if (result == QDialog::Accepted && cpu == get_cpu() && cpu == cpu_check()) + { + PerformGoToRequest(expression_input->text()); + } - dlg->deleteLater(); + m_goto_dialog = nullptr; + }); + + m_goto_dialog->show(); +} + +void debugger_frame::PerformGoToRequest(const QString& text_argument) +{ + const u64 address = EvaluateExpression(text_argument); + + if (address != umax) + { + m_debugger_list->ShowAddress(static_cast(address), true); + } } u64 debugger_frame::EvaluateExpression(const QString& expression) @@ -1077,8 +1103,8 @@ u64 debugger_frame::EvaluateExpression(const QString& expression) const u64 res = static_cast(fixed_expression.toULong(&ok, 16)); if (ok) return res; - if (const auto thread = get_cpu()) return thread->get_pc(); - return 0; + if (const auto thread = get_cpu(); thread && expression.isEmpty()) return thread->get_pc(); + return umax; } void debugger_frame::ClearBreakpoints() const diff --git a/rpcs3/rpcs3qt/debugger_frame.h b/rpcs3/rpcs3qt/debugger_frame.h index d9575db065..0bfd9a1563 100644 --- a/rpcs3/rpcs3qt/debugger_frame.h +++ b/rpcs3/rpcs3qt/debugger_frame.h @@ -71,6 +71,7 @@ class debugger_frame : public custom_dock_widget call_stack_list* m_call_stack_list; instruction_editor_dialog* m_inst_editor = nullptr; register_editor_dialog* m_reg_editor = nullptr; + QDialog* m_goto_dialog = nullptr; std::shared_ptr m_gui_settings; @@ -91,6 +92,7 @@ public: void WritePanels(); void EnableButtons(bool enable); void ShowGotoAddressDialog(); + void PerformGoToRequest(const QString& text_argument); u64 EvaluateExpression(const QString& expression); void ClearBreakpoints() const; // Fallthrough method into breakpoint_list. void ClearCallStack(); diff --git a/rpcs3/rpcs3qt/log_frame.cpp b/rpcs3/rpcs3qt/log_frame.cpp index 453252fb80..3ba7ec65a1 100644 --- a/rpcs3/rpcs3qt/log_frame.cpp +++ b/rpcs3/rpcs3qt/log_frame.cpp @@ -241,6 +241,13 @@ void log_frame::CreateAndConnectActions() m_tty->clear(); }); + m_perform_goto_on_debugger = new QAction(tr("Go-To On The Debugger"), this); + connect(m_perform_goto_on_debugger, &QAction::triggered, [this]() + { + QPlainTextEdit* pte = (m_tabWidget->currentIndex() == 1 ? m_tty : m_log); + Q_EMIT PerformGoToOnDebugger(pte->textCursor().selectedText()); + }); + m_stack_act_tty = new QAction(tr("Stack Mode (TTY)"), this); m_stack_act_tty->setCheckable(true); connect(m_stack_act_tty, &QAction::toggled, [this](bool checked) @@ -336,6 +343,13 @@ void log_frame::CreateAndConnectActions() { QMenu* menu = m_log->createStandardContextMenu(); menu->addAction(m_clear_act); + menu->addAction(m_perform_goto_on_debugger); + + std::shared_ptr goto_signal_accepted = std::make_shared(false); + Q_EMIT PerformGoToOnDebugger("", true, goto_signal_accepted); + m_perform_goto_on_debugger->setEnabled(m_log->textCursor().hasSelection() && *goto_signal_accepted); + m_perform_goto_on_debugger->setToolTip(tr("Jump to the selected hexadecimal address from the log text on the debugger.")); + menu->addSeparator(); menu->addActions(m_log_level_acts->actions()); menu->addSeparator(); @@ -349,6 +363,13 @@ void log_frame::CreateAndConnectActions() { QMenu* menu = m_tty->createStandardContextMenu(); menu->addAction(m_clear_tty_act); + menu->addAction(m_perform_goto_on_debugger); + + std::shared_ptr goto_signal_accepted = std::make_shared(false); + Q_EMIT PerformGoToOnDebugger("", true, goto_signal_accepted); + m_perform_goto_on_debugger->setEnabled(m_tty->textCursor().hasSelection() && *goto_signal_accepted); + m_perform_goto_on_debugger->setToolTip(tr("Jump to the selected hexadecimal address from the TTY text on the debugger.")); + menu->addSeparator(); menu->addAction(m_tty_act); menu->addAction(m_stack_act_tty); diff --git a/rpcs3/rpcs3qt/log_frame.h b/rpcs3/rpcs3qt/log_frame.h index fcc85df698..fc2b8c1b7b 100644 --- a/rpcs3/rpcs3qt/log_frame.h +++ b/rpcs3/rpcs3qt/log_frame.h @@ -30,6 +30,7 @@ public Q_SLOTS: Q_SIGNALS: void LogFrameClosed(); + void PerformGoToOnDebugger(const QString& text_argument, bool test_only = false, std::shared_ptr signal_accepted = nullptr); protected: /** Override inherited method from Qt to allow signalling when close happened.*/ void closeEvent(QCloseEvent* event) override; @@ -71,6 +72,7 @@ private: QAction* m_clear_act = nullptr; QAction* m_clear_tty_act = nullptr; + QAction* m_perform_goto_on_debugger = nullptr; QActionGroup* m_log_level_acts = nullptr; QAction* m_nothing_act = nullptr; diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index 89af9b020e..15bc6ffe98 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -2793,6 +2793,22 @@ void main_window::CreateDockWindows() } }); + connect(m_log_frame, &log_frame::PerformGoToOnDebugger, this, [this](const QString& text_argument, bool test_only, std::shared_ptr signal_accepted) + { + if (m_debugger_frame && m_debugger_frame->isVisible()) + { + if (signal_accepted) + { + *signal_accepted = true; + } + + if (!test_only) + { + m_debugger_frame->PerformGoToRequest(text_argument); + } + } + }); + connect(m_debugger_frame, &debugger_frame::DebugFrameClosed, this, [this]() { if (ui->showDebuggerAct->isChecked())