diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui index eccea143189..18a092ca2d0 100644 --- a/src/qt/forms/debugwindow.ui +++ b/src/qt/forms/debugwindow.ui @@ -570,6 +570,32 @@ + + + + Clear console output and history. + + + Qt::LeftToRight + + + + + + + :/icons/transaction_abandoned:/icons/transaction_abandoned + + + + 22 + 22 + + + + Ctrl+Shift+L + + + diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 958c82fda22..abad04a0f28 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -93,6 +93,9 @@ public Q_SLOTS: Q_SIGNALS: void reply(int category, const QString &command); + void clearScreen(); + void clearHistory(); + void printHistory(); private: interfaces::Node& m_node; @@ -402,7 +405,21 @@ void RPCExecutor::request(const QString &command, const QString& wallet_name) " example: getblock(getblockhash(0) 1)[tx]\n\n" "Results without keys can be queried with an integer in brackets using the parenthesized syntax.\n" - " example: getblock(getblockhash(0),1)[tx][0]\n\n"))); + " example: getblock(getblockhash(0),1)[tx][0]\n\n" + "Console commands:\n" + " clear Clears the screen.\n" + " history-clear Clears the command history and the screen.\n" + " history Prints all command history.\n\n" + ))); + return; + } else if (executableCommand == "clear\n") { + Q_EMIT clearScreen(); + return; + } else if (executableCommand == "history-clear\n") { + Q_EMIT clearHistory(); + return; + } else if (executableCommand == "history\n") { + Q_EMIT printHistory(); return; } if (!RPCConsole::RPCExecuteCommandLine(m_node, result, executableCommand, nullptr, wallet_name)) { @@ -506,6 +523,7 @@ RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformSty ui->openDebugLogfileButton->setIcon(platformStyle->SingleColorIcon(":/icons/export")); } ui->clearButton->setIcon(platformStyle->SingleColorIcon(":/icons/remove")); + ui->resetButton->setIcon(platformStyle->SingleColorIcon(":/icons/transaction_abandoned")); // Trash icon ui->fontBiggerButton->setIcon(platformStyle->SingleColorIcon(":/icons/fontbigger")); //: Main shortcut to increase the RPC console font size. @@ -527,7 +545,11 @@ RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformSty ui->messagesWidget->installEventFilter(this); connect(ui->hidePeersDetailButton, &QAbstractButton::clicked, this, &RPCConsole::clearSelectedNode); - connect(ui->clearButton, &QAbstractButton::clicked, [this] { clear(); }); + connect(ui->clearButton, &QAbstractButton::clicked, [this]() { clear(); }); + connect(ui->resetButton, &QAbstractButton::clicked, [this]() { + history.clear(); + clear(false); + }); connect(ui->fontBiggerButton, &QAbstractButton::clicked, this, &RPCConsole::fontBigger); connect(ui->fontSmallerButton, &QAbstractButton::clicked, this, &RPCConsole::fontSmaller); connect(ui->btnClearTrafficGraph, &QPushButton::clicked, ui->trafficGraph, &TrafficGraphWidget::clear); @@ -728,6 +750,9 @@ void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_ } wordList << "help-console"; + wordList << "clear"; + wordList << "history-clear"; + wordList << "history"; wordList.sort(); autoCompleter = new QCompleter(wordList, this); autoCompleter->setModelSorting(QCompleter::CaseSensitivelySortedModel); @@ -863,6 +888,7 @@ void RPCConsole::clear(bool keep_prompt) they are not space separated from the rest of the text intentionally. */ tr("Welcome to the %1 RPC console.\n" "Use up and down arrows to navigate history, and %2 to clear screen.\n" + "Use %9 to reset the console, clearing both the screen and command history.\n" "Use %3 and %4 to increase or decrease the font size.\n" "Type %5 for an overview of available commands.\n" "For more information on using this console, type %6.\n" @@ -877,7 +903,8 @@ void RPCConsole::clear(bool keep_prompt) "help", "help-console", "", - ""); + "", + "" + ui->resetButton->shortcut().toString(QKeySequence::NativeText) + ""); message(CMD_REPLY, welcome_message, true); } @@ -1077,6 +1104,15 @@ void RPCConsole::browseHistory(int offset) ui->lineEdit->setText(cmd); } +void RPCConsole::finishCommand(const std::function& action) +{ + // Remove "Executing…" message. + ui->messagesWidget->undo(); + action(); + scrollToEnd(); + m_is_executing = false; +} + void RPCConsole::startExecutor() { m_executor = new RPCExecutor(m_node); @@ -1084,11 +1120,27 @@ void RPCConsole::startExecutor() // Replies from executor object must go to this object connect(m_executor, &RPCExecutor::reply, this, [this](int category, const QString& command) { - // Remove "Executing…" message. - ui->messagesWidget->undo(); - message(category, command); - scrollToEnd(); - m_is_executing = false; + finishCommand([this, category, command]() { message(category, command); }); + }); + connect(m_executor, &RPCExecutor::clearScreen, this, [this]() { + finishCommand([this]() { clear(false); }); + }); + connect(m_executor, &RPCExecutor::clearHistory, this, [this]() { + finishCommand([this]() { + history.clear(); + message(CMD_REPLY, tr("History has been cleared.")); + }); + }); + connect(m_executor, &RPCExecutor::printHistory, this, [this]() { + finishCommand([this]() { + QStringList out; + out.reserve(history.size()); + qsizetype index = 0; + for (const QString& entry : history) { + out << QStringLiteral("%1: %2").arg(++index).arg(entry); + } + message(CMD_REPLY, out.join(QStringLiteral("\n"))); + }); }); // Make sure executor object is deleted in its own thread diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index a1b9522b98e..de4dde43ab6 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -104,6 +104,7 @@ private Q_SLOTS: void clearSelectedNode(); /** show detailed information on ui about selected node */ void updateDetailWidget(); + void finishCommand(const std::function& action); public Q_SLOTS: void clear(bool keep_prompt = false);