Merge bitcoin-core/gui#123: rpc: Do not accept command while executing another one

38eb37c0bd29b4cb825de905e8eec87636a5221b qt, rpc: Do not accept command while executing another one (Hennadii Stepanov)
0c32b9c5273a4933bda90aa9eb9b7eace6dcaa14 qt, rpc: Accept stop RPC even another command is executing (Hennadii Stepanov)
ccf790287c53edbc7b18983e07f520823436c003 qt, rpc, refactor: Return early in RPCConsole::on_lineEdit_returnPressed (Hennadii Stepanov)
5b9c8c9cdd8e12d2e477840df9d6ab809a613c12 qt, rpc: Add "Executing…" message (Hennadii Stepanov)

Pull request description:

  On master (3f512f3d563954547061ee743648b57a900cbe04) it is possible to enter another command while the current command is still being executed. That makes a mess in the output.

  With this PR:
  ![Screenshot from 2020-10-29 20-48-55](https://user-images.githubusercontent.com/32963518/97619690-329c0880-1a29-11eb-9f5b-6ae3c02c13b2.png)

  Some previous context: https://github.com/bitcoin-core/gui/pull/59#issuecomment-715275185

  ---

  It is still possible to enter and execute the `stop` command any time.

ACKs for top commit:
  jarolrod:
    ACK  38eb37c
  promag:
    Tested ACK 38eb37c0bd29b4cb825de905e8eec87636a5221b.

Tree-SHA512: 2b37a4b6838bf586b1b5c878192106721f713caeb6252514a6540356aab898986396e0777e73891d331b1be797a4926c20d3f9f38ba2c984ea90d55b0c34f664
This commit is contained in:
Hennadii Stepanov 2021-06-01 03:25:23 +03:00 committed by Konstantin Akimov
parent 19310646e0
commit 5a0d524506
No known key found for this signature in database
GPG Key ID: 2176C4A5D01EA524
3 changed files with 65 additions and 44 deletions

View File

@ -1080,57 +1080,71 @@ void RPCConsole::showPage(int index)
void RPCConsole::on_lineEdit_returnPressed() void RPCConsole::on_lineEdit_returnPressed()
{ {
QString cmd = ui->lineEdit->text(); QString cmd = ui->lineEdit->text().trimmed();
if(!cmd.isEmpty()) if (cmd.isEmpty()) {
{ return;
std::string strFilteredCmd; }
try {
std::string dummy; std::string strFilteredCmd;
if (!RPCParseCommandLine(nullptr, dummy, cmd.toStdString(), false, &strFilteredCmd)) { try {
// Failed to parse command, so we cannot even filter it for the history std::string dummy;
throw std::runtime_error("Invalid command line"); if (!RPCParseCommandLine(nullptr, dummy, cmd.toStdString(), false, &strFilteredCmd)) {
} // Failed to parse command, so we cannot even filter it for the history
} catch (const std::exception& e) { throw std::runtime_error("Invalid command line");
QMessageBox::critical(this, "Error", QString("Error: ") + QString::fromStdString(e.what()));
return;
} }
} catch (const std::exception& e) {
QMessageBox::critical(this, "Error", QString("Error: ") + QString::fromStdString(e.what()));
return;
}
ui->lineEdit->clear(); // A special case allows to request shutdown even a long-running command is executed.
if (cmd == QLatin1String("stop")) {
std::string dummy;
RPCExecuteCommandLine(m_node, dummy, cmd.toStdString());
return;
}
cmdBeforeBrowsing = QString(); if (m_is_executing) {
return;
}
ui->lineEdit->clear();
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
WalletModel* wallet_model = ui->WalletSelector->currentData().value<WalletModel*>(); WalletModel* wallet_model = ui->WalletSelector->currentData().value<WalletModel*>();
if (m_last_wallet_model != wallet_model) { if (m_last_wallet_model != wallet_model) {
if (wallet_model) { if (wallet_model) {
message(CMD_REQUEST, tr("Executing command using \"%1\" wallet").arg(wallet_model->getWalletName())); message(CMD_REQUEST, tr("Executing command using \"%1\" wallet").arg(wallet_model->getWalletName()));
} else { } else {
message(CMD_REQUEST, tr("Executing command without any wallet")); message(CMD_REQUEST, tr("Executing command without any wallet"));
}
m_last_wallet_model = wallet_model;
} }
#endif m_last_wallet_model = wallet_model;
message(CMD_REQUEST, QString::fromStdString(strFilteredCmd));
Q_EMIT cmdRequest(cmd, m_last_wallet_model);
cmd = QString::fromStdString(strFilteredCmd);
// Remove command, if already in history
history.removeOne(cmd);
// Append command to history
history.append(cmd);
// Enforce maximum history size
while(history.size() > CONSOLE_HISTORY)
history.removeFirst();
// Set pointer to end of history
historyPtr = history.size();
// Scroll console view to end
scrollToEnd();
} }
#endif // ENABLE_WALLET
message(CMD_REQUEST, QString::fromStdString(strFilteredCmd));
//: A console message indicating an entered command is currently being executed.
message(CMD_REPLY, tr("Executing…"));
m_is_executing = true;
Q_EMIT cmdRequest(cmd, m_last_wallet_model);
cmd = QString::fromStdString(strFilteredCmd);
// Remove command, if already in history
history.removeOne(cmd);
// Append command to history
history.append(cmd);
// Enforce maximum history size
while (history.size() > CONSOLE_HISTORY) {
history.removeFirst();
}
// Set pointer to end of history
historyPtr = history.size();
// Scroll console view to end
scrollToEnd();
} }
void RPCConsole::browseHistory(int offset) void RPCConsole::browseHistory(int offset)
@ -1160,7 +1174,13 @@ void RPCConsole::startExecutor()
executor->moveToThread(&thread); executor->moveToThread(&thread);
// Replies from executor object must go to this object // Replies from executor object must go to this object
connect(executor, &RPCExecutor::reply, this, qOverload<int, const QString&>(&RPCConsole::message)); connect(executor, &RPCExecutor::reply, this, [this](int category, const QString& command) {
// Remove "Executing…" message.
ui->messagesWidget->undo();
message(category, command);
scrollToEnd();
m_is_executing = false;
});
// Requests from this object must go to executor // Requests from this object must go to executor
connect(this, &RPCConsole::cmdRequest, executor, &RPCExecutor::request); connect(this, &RPCConsole::cmdRequest, executor, &RPCExecutor::request);

View File

@ -189,6 +189,7 @@ private:
QCompleter *autoCompleter = nullptr; QCompleter *autoCompleter = nullptr;
QThread thread; QThread thread;
WalletModel* m_last_wallet_model{nullptr}; WalletModel* m_last_wallet_model{nullptr};
bool m_is_executing{false};
/** Update UI with latest network info from model. */ /** Update UI with latest network info from model. */
void updateNetworkState(); void updateNetworkState();

View File

@ -41,7 +41,7 @@ void TestRpcCommand(RPCConsole* console)
QTest::keyClicks(lineEdit, "getblockchaininfo"); QTest::keyClicks(lineEdit, "getblockchaininfo");
QTest::keyClick(lineEdit, Qt::Key_Return); QTest::keyClick(lineEdit, Qt::Key_Return);
QVERIFY(mw_spy.wait(1000)); QVERIFY(mw_spy.wait(1000));
QCOMPARE(mw_spy.count(), 2); QCOMPARE(mw_spy.count(), 4);
QString output = messagesWidget->toPlainText(); QString output = messagesWidget->toPlainText();
UniValue value; UniValue value;
value.read(output.right(output.size() - output.indexOf("{")).toStdString()); value.read(output.right(output.size() - output.indexOf("{")).toStdString());