aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/qt/bitcoingui.cpp36
-rw-r--r--src/qt/bitcoingui.h6
-rw-r--r--src/qt/rpcconsole.cpp144
-rw-r--r--src/qt/rpcconsole.h1
-rw-r--r--src/qt/test/apptests.cpp2
-rw-r--r--src/test/bip32_tests.cpp18
6 files changed, 136 insertions, 71 deletions
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 100022bac1..e5dde88bd1 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -43,6 +43,7 @@
#include <QAction>
#include <QApplication>
#include <QComboBox>
+#include <QCursor>
#include <QDateTime>
#include <QDragEnterEvent>
#include <QListWidget>
@@ -199,9 +200,6 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
// Subscribe to notifications from core
subscribeToCoreSignals();
- connect(connectionsControl, &GUIUtil::ClickableLabel::clicked, [this] {
- m_node.setNetworkActive(!m_node.getNetworkActive());
- });
connect(labelProxyIcon, &GUIUtil::ClickableLabel::clicked, [this] {
openOptionsDialogWithTab(OptionsDialog::TAB_NETWORK);
});
@@ -586,7 +584,10 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel, interfaces::BlockAndH
createTrayIconMenu();
// Keep up to date with client
- updateNetworkState();
+ setNetworkActive(m_node.getNetworkActive());
+ connect(connectionsControl, &GUIUtil::ClickableLabel::clicked, [this] {
+ GUIUtil::PopupMenu(m_network_context_menu, QCursor::pos());
+ });
connect(_clientModel, &ClientModel::numConnectionsChanged, this, &BitcoinGUI::setNumConnections);
connect(_clientModel, &ClientModel::networkActiveChanged, this, &BitcoinGUI::setNetworkActive);
@@ -915,14 +916,18 @@ void BitcoinGUI::updateNetworkState()
QString tooltip;
if (m_node.getNetworkActive()) {
- tooltip = tr("%n active connection(s) to Bitcoin network", "", count) + QString(".<br>") + tr("Click to disable network activity.");
+ //: A substring of the tooltip.
+ tooltip = tr("%n active connection(s) to Bitcoin network.", "", count);
} else {
- tooltip = tr("Network activity disabled.") + QString("<br>") + tr("Click to enable network activity again.");
+ //: A substring of the tooltip.
+ tooltip = tr("Network activity disabled.");
icon = ":/icons/network_disabled";
}
// Don't word-wrap this (fixed-width) tooltip
- tooltip = QString("<nobr>") + tooltip + QString("</nobr>");
+ tooltip = QLatin1String("<nobr>") + tooltip + QLatin1String("<br>") +
+ //: A substring of the tooltip. "More actions" are available via the context menu.
+ tr("Click for more actions.") + QLatin1String("</nobr>");
connectionsControl->setToolTip(tooltip);
connectionsControl->setThemedPixmap(icon, STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE);
@@ -933,9 +938,24 @@ void BitcoinGUI::setNumConnections(int count)
updateNetworkState();
}
-void BitcoinGUI::setNetworkActive(bool networkActive)
+void BitcoinGUI::setNetworkActive(bool network_active)
{
updateNetworkState();
+ m_network_context_menu->clear();
+ m_network_context_menu->addAction(
+ //: A context menu item. The "Peers tab" is an element of the "Node window".
+ tr("Show Peers tab"),
+ [this] {
+ rpcConsole->setTabFocus(RPCConsole::TabTypes::PEERS);
+ showDebugWindow();
+ });
+ m_network_context_menu->addAction(
+ network_active ?
+ //: A context menu item.
+ tr("Disable network activity") :
+ //: A context menu item. The network activity was disabled previously.
+ tr("Enable network activity"),
+ [this, new_state = !network_active] { m_node.setNetworkActive(new_state); });
}
void BitcoinGUI::updateHeadersSyncProgressLabel()
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 65c5331d32..c83cd446a0 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -17,6 +17,7 @@
#include <QLabel>
#include <QMainWindow>
#include <QMap>
+#include <QMenu>
#include <QPoint>
#include <QSystemTrayIcon>
@@ -51,7 +52,6 @@ QT_BEGIN_NAMESPACE
class QAction;
class QComboBox;
class QDateTime;
-class QMenu;
class QProgressBar;
class QProgressDialog;
QT_END_NAMESPACE
@@ -175,6 +175,8 @@ private:
HelpMessageDialog* helpMessageDialog = nullptr;
ModalOverlay* modalOverlay = nullptr;
+ QMenu* m_network_context_menu = new QMenu(this);
+
#ifdef Q_OS_MAC
CAppNapInhibitor* m_app_nap_inhibitor = nullptr;
#endif
@@ -222,7 +224,7 @@ public Q_SLOTS:
/** Set number of connections shown in the UI */
void setNumConnections(int count);
/** Set network state shown in the UI */
- void setNetworkActive(bool networkActive);
+ void setNetworkActive(bool network_active);
/** Set number of blocks and last block date shown in the UI */
void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers, SynchronizationState sync_state);
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index fa964a84ed..548b8cb34d 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -816,23 +816,29 @@ void RPCConsole::clear(bool keep_prompt)
).arg(fixedFontInfo.family(), QString("%1pt").arg(consoleFontSize))
);
- message(CMD_REPLY,
- tr("Welcome to the %1 RPC console.").arg(PACKAGE_NAME) +
- "<br>" +
- tr("Use up and down arrows to navigate history, and %1 to clear screen.")
- .arg("<b>" + ui->clearButton->shortcut().toString(QKeySequence::NativeText) + "</b>") +
- "<br>" +
- tr("Use %1 and %2 to increase or decrease the font size.")
- .arg("<b>" + ui->fontBiggerButton->shortcut().toString(QKeySequence::NativeText) + "</b>")
- .arg("<b>" + ui->fontSmallerButton->shortcut().toString(QKeySequence::NativeText) + "</b>") +
- "<br>" +
- tr("Type %1 for an overview of available commands.").arg("<b>help</b>") +
- "<br>" +
- tr("For more information on using this console type %1.").arg("<b>help-console</b>") +
- "<br><span class=\"secwarning\"><br>" +
- tr("WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.") +
- "</span>",
- true);
+ static const QString welcome_message =
+ /*: RPC console welcome message.
+ Placeholders %7 and %8 are style tags for the warning content, and
+ 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 %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"
+ "\n"
+ "%7WARNING: Scammers have been active, telling users to type"
+ " commands here, stealing their wallet contents. Do not use this console"
+ " without fully understanding the ramifications of a command.%8")
+ .arg(PACKAGE_NAME,
+ "<b>" + ui->clearButton->shortcut().toString(QKeySequence::NativeText) + "</b>",
+ "<b>" + ui->fontBiggerButton->shortcut().toString(QKeySequence::NativeText) + "</b>",
+ "<b>" + ui->fontSmallerButton->shortcut().toString(QKeySequence::NativeText) + "</b>",
+ "<b>help</b>",
+ "<b>help-console</b>",
+ "<span class=\"secwarning\">",
+ "<span>");
+
+ message(CMD_REPLY, welcome_message, true);
}
void RPCConsole::keyPressEvent(QKeyEvent *event)
@@ -924,57 +930,71 @@ void RPCConsole::setMempoolSize(long numberOfTxs, size_t dynUsage)
void RPCConsole::on_lineEdit_returnPressed()
{
- QString cmd = ui->lineEdit->text();
+ QString cmd = ui->lineEdit->text().trimmed();
- if(!cmd.isEmpty())
- {
- std::string strFilteredCmd;
- try {
- std::string dummy;
- if (!RPCParseCommandLine(nullptr, dummy, cmd.toStdString(), false, &strFilteredCmd)) {
- // Failed to parse command, so we cannot even filter it for the history
- throw std::runtime_error("Invalid command line");
- }
- } catch (const std::exception& e) {
- QMessageBox::critical(this, "Error", QString("Error: ") + QString::fromStdString(e.what()));
- return;
+ if (cmd.isEmpty()) {
+ return;
+ }
+
+ std::string strFilteredCmd;
+ try {
+ std::string dummy;
+ if (!RPCParseCommandLine(nullptr, dummy, cmd.toStdString(), false, &strFilteredCmd)) {
+ // Failed to parse command, so we cannot even filter it for the history
+ throw std::runtime_error("Invalid command line");
}
+ } catch (const std::exception& e) {
+ QMessageBox::critical(this, "Error", QString("Error: ") + QString::fromStdString(e.what()));
+ return;
+ }
+
+ // 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;
+ }
- ui->lineEdit->clear();
+ if (m_is_executing) {
+ return;
+ }
- cmdBeforeBrowsing = QString();
+ ui->lineEdit->clear();
#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 (wallet_model) {
- message(CMD_REQUEST, tr("Executing command using \"%1\" wallet").arg(wallet_model->getWalletName()));
- } else {
- message(CMD_REQUEST, tr("Executing command without any wallet"));
- }
- m_last_wallet_model = wallet_model;
+ if (m_last_wallet_model != wallet_model) {
+ if (wallet_model) {
+ message(CMD_REQUEST, tr("Executing command using \"%1\" wallet").arg(wallet_model->getWalletName()));
+ } else {
+ message(CMD_REQUEST, tr("Executing command without any wallet"));
}
-#endif
-
- 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();
+ m_last_wallet_model = wallet_model;
+ }
+#endif // ENABLE_WALLET
- // Scroll console view to end
- scrollToEnd();
+ 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)
@@ -1004,7 +1024,13 @@ void RPCConsole::startExecutor()
executor->moveToThread(&thread);
// 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
connect(this, &RPCConsole::cmdRequest, executor, &RPCExecutor::request);
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index 55a1decceb..75f466642b 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -166,6 +166,7 @@ private:
QCompleter *autoCompleter = nullptr;
QThread thread;
WalletModel* m_last_wallet_model{nullptr};
+ bool m_is_executing{false};
/** Update UI with latest network info from model. */
void updateNetworkState();
diff --git a/src/qt/test/apptests.cpp b/src/qt/test/apptests.cpp
index c1d5f84be5..cb3dbd2267 100644
--- a/src/qt/test/apptests.cpp
+++ b/src/qt/test/apptests.cpp
@@ -40,7 +40,7 @@ void TestRpcCommand(RPCConsole* console)
QTest::keyClicks(lineEdit, "getblockchaininfo");
QTest::keyClick(lineEdit, Qt::Key_Return);
QVERIFY(mw_spy.wait(1000));
- QCOMPARE(mw_spy.count(), 2);
+ QCOMPARE(mw_spy.count(), 4);
QString output = messagesWidget->toPlainText();
UniValue value;
value.read(output.right(output.size() - output.lastIndexOf(QChar::ObjectReplacementCharacter) - 1).toStdString());
diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp
index 32329eb510..fb16c92647 100644
--- a/src/test/bip32_tests.cpp
+++ b/src/test/bip32_tests.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2013-2020 The Bitcoin Core developers
+// Copyright (c) 2013-2021 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -87,6 +87,18 @@ TestVector test3 =
"xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L",
0);
+TestVector test4 =
+ TestVector("3ddd5602285899a946114506157c7997e5444528f3003f6134712147db19b678")
+ ("xpub661MyMwAqRbcGczjuMoRm6dXaLDEhW1u34gKenbeYqAix21mdUKJyuyu5F1rzYGVxyL6tmgBUAEPrEz92mBXjByMRiJdba9wpnN37RLLAXa",
+ "xprv9s21ZrQH143K48vGoLGRPxgo2JNkJ3J3fqkirQC2zVdk5Dgd5w14S7fRDyHH4dWNHUgkvsvNDCkvAwcSHNAQwhwgNMgZhLtQC63zxwhQmRv",
+ 0x80000000)
+ ("xpub69AUMk3qDBi3uW1sXgjCmVjJ2G6WQoYSnNHyzkmdCHEhSZ4tBok37xfFEqHd2AddP56Tqp4o56AePAgCjYdvpW2PU2jbUPFKsav5ut6Ch1m",
+ "xprv9vB7xEWwNp9kh1wQRfCCQMnZUEG21LpbR9NPCNN1dwhiZkjjeGRnaALmPXCX7SgjFTiCTT6bXes17boXtjq3xLpcDjzEuGLQBM5ohqkao9G",
+ 0x80000001)
+ ("xpub6BJA1jSqiukeaesWfxe6sNK9CCGaujFFSJLomWHprUL9DePQ4JDkM5d88n49sMGJxrhpjazuXYWdMf17C9T5XnxkopaeS7jGk1GyyVziaMt",
+ "xprv9xJocDuwtYCMNAo3Zw76WENQeAS6WGXQ55RCy7tDJ8oALr4FWkuVoHJeHVAcAqiZLE7Je3vZJHxspZdFHfnBEjHqU5hG1Jaj32dVoS6XLT1",
+ 0);
+
static void RunTest(const TestVector &test) {
std::vector<unsigned char> seed = ParseHex(test.strHexMaster);
CExtKey key;
@@ -135,4 +147,8 @@ BOOST_AUTO_TEST_CASE(bip32_test3) {
RunTest(test3);
}
+BOOST_AUTO_TEST_CASE(bip32_test4) {
+ RunTest(test4);
+}
+
BOOST_AUTO_TEST_SUITE_END()