Bitcoin Core  22.99.0
P2P Digital Currency
rpcconsole.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2021 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #if defined(HAVE_CONFIG_H)
7 #endif
8 
9 #include <qt/rpcconsole.h>
10 #include <qt/forms/ui_debugwindow.h>
11 
12 #include <chainparams.h>
13 #include <interfaces/node.h>
14 #include <netbase.h>
15 #include <qt/bantablemodel.h>
16 #include <qt/clientmodel.h>
17 #include <qt/guiutil.h>
18 #include <qt/peertablesortproxy.h>
19 #include <qt/platformstyle.h>
20 #include <qt/walletmodel.h>
21 #include <rpc/client.h>
22 #include <rpc/server.h>
23 #include <util/strencodings.h>
24 #include <util/string.h>
25 #include <util/system.h>
26 #include <util/threadnames.h>
27 
28 #include <univalue.h>
29 
30 #ifdef ENABLE_WALLET
31 #ifdef USE_BDB
32 #include <wallet/bdb.h>
33 #endif
34 #include <wallet/db.h>
35 #include <wallet/wallet.h>
36 #endif
37 
38 #include <QAbstractButton>
39 #include <QAbstractItemModel>
40 #include <QDateTime>
41 #include <QFont>
42 #include <QKeyEvent>
43 #include <QLatin1String>
44 #include <QLocale>
45 #include <QMenu>
46 #include <QMessageBox>
47 #include <QScreen>
48 #include <QScrollBar>
49 #include <QSettings>
50 #include <QString>
51 #include <QStringList>
52 #include <QStyledItemDelegate>
53 #include <QTime>
54 #include <QTimer>
55 #include <QVariant>
56 
57 #include <chrono>
58 
59 const int CONSOLE_HISTORY = 50;
61 const QSize FONT_RANGE(4, 40);
62 const char fontSizeSettingsKey[] = "consoleFontSize";
63 
64 const struct {
65  const char *url;
66  const char *source;
67 } ICON_MAPPING[] = {
68  {"cmd-request", ":/icons/tx_input"},
69  {"cmd-reply", ":/icons/tx_output"},
70  {"cmd-error", ":/icons/tx_output"},
71  {"misc", ":/icons/tx_inout"},
72  {nullptr, nullptr}
73 };
74 
75 namespace {
76 
77 // don't add private key handling cmd's to the history
78 const QStringList historyFilter = QStringList()
79  << "importprivkey"
80  << "importmulti"
81  << "sethdseed"
82  << "signmessagewithprivkey"
83  << "signrawtransactionwithkey"
84  << "walletpassphrase"
85  << "walletpassphrasechange"
86  << "encryptwallet";
87 
88 }
89 
90 /* Object for executing console RPC commands in a separate thread.
91 */
92 class RPCExecutor : public QObject
93 {
94  Q_OBJECT
95 public:
97 
98 public Q_SLOTS:
99  void request(const QString &command, const WalletModel* wallet_model);
100 
101 Q_SIGNALS:
102  void reply(int category, const QString &command);
103 
104 private:
106 };
107 
111 class QtRPCTimerBase: public QObject, public RPCTimerBase
112 {
113  Q_OBJECT
114 public:
115  QtRPCTimerBase(std::function<void()>& _func, int64_t millis):
116  func(_func)
117  {
118  timer.setSingleShot(true);
119  connect(&timer, &QTimer::timeout, [this]{ func(); });
120  timer.start(millis);
121  }
123 private:
124  QTimer timer;
125  std::function<void()> func;
126 };
127 
129 {
130 public:
132  const char *Name() override { return "Qt"; }
133  RPCTimerBase* NewTimer(std::function<void()>& func, int64_t millis) override
134  {
135  return new QtRPCTimerBase(func, millis);
136  }
137 };
138 
139 class PeerIdViewDelegate : public QStyledItemDelegate
140 {
141  Q_OBJECT
142 public:
143  explicit PeerIdViewDelegate(QObject* parent = nullptr)
144  : QStyledItemDelegate(parent) {}
145 
146  QString displayText(const QVariant& value, const QLocale& locale) const override
147  {
148  // Additional spaces should visually separate right-aligned content
149  // from the next column to the right.
150  return value.toString() + QLatin1String(" ");
151  }
152 };
153 
154 #include <qt/rpcconsole.moc>
155 
176 bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strResult, const std::string &strCommand, const bool fExecute, std::string * const pstrFilteredOut, const WalletModel* wallet_model)
177 {
178  std::vector< std::vector<std::string> > stack;
179  stack.push_back(std::vector<std::string>());
180 
181  enum CmdParseState
182  {
183  STATE_EATING_SPACES,
184  STATE_EATING_SPACES_IN_ARG,
185  STATE_EATING_SPACES_IN_BRACKETS,
186  STATE_ARGUMENT,
187  STATE_SINGLEQUOTED,
188  STATE_DOUBLEQUOTED,
189  STATE_ESCAPE_OUTER,
190  STATE_ESCAPE_DOUBLEQUOTED,
191  STATE_COMMAND_EXECUTED,
192  STATE_COMMAND_EXECUTED_INNER
193  } state = STATE_EATING_SPACES;
194  std::string curarg;
195  UniValue lastResult;
196  unsigned nDepthInsideSensitive = 0;
197  size_t filter_begin_pos = 0, chpos;
198  std::vector<std::pair<size_t, size_t>> filter_ranges;
199 
200  auto add_to_current_stack = [&](const std::string& strArg) {
201  if (stack.back().empty() && (!nDepthInsideSensitive) && historyFilter.contains(QString::fromStdString(strArg), Qt::CaseInsensitive)) {
202  nDepthInsideSensitive = 1;
203  filter_begin_pos = chpos;
204  }
205  // Make sure stack is not empty before adding something
206  if (stack.empty()) {
207  stack.push_back(std::vector<std::string>());
208  }
209  stack.back().push_back(strArg);
210  };
211 
212  auto close_out_params = [&]() {
213  if (nDepthInsideSensitive) {
214  if (!--nDepthInsideSensitive) {
215  assert(filter_begin_pos);
216  filter_ranges.push_back(std::make_pair(filter_begin_pos, chpos));
217  filter_begin_pos = 0;
218  }
219  }
220  stack.pop_back();
221  };
222 
223  std::string strCommandTerminated = strCommand;
224  if (strCommandTerminated.back() != '\n')
225  strCommandTerminated += "\n";
226  for (chpos = 0; chpos < strCommandTerminated.size(); ++chpos)
227  {
228  char ch = strCommandTerminated[chpos];
229  switch(state)
230  {
231  case STATE_COMMAND_EXECUTED_INNER:
232  case STATE_COMMAND_EXECUTED:
233  {
234  bool breakParsing = true;
235  switch(ch)
236  {
237  case '[': curarg.clear(); state = STATE_COMMAND_EXECUTED_INNER; break;
238  default:
239  if (state == STATE_COMMAND_EXECUTED_INNER)
240  {
241  if (ch != ']')
242  {
243  // append char to the current argument (which is also used for the query command)
244  curarg += ch;
245  break;
246  }
247  if (curarg.size() && fExecute)
248  {
249  // if we have a value query, query arrays with index and objects with a string key
250  UniValue subelement;
251  if (lastResult.isArray())
252  {
253  const auto parsed{ToIntegral<size_t>(curarg)};
254  if (!parsed) {
255  throw std::runtime_error("Invalid result query");
256  }
257  subelement = lastResult[parsed.value()];
258  }
259  else if (lastResult.isObject())
260  subelement = find_value(lastResult, curarg);
261  else
262  throw std::runtime_error("Invalid result query"); //no array or object: abort
263  lastResult = subelement;
264  }
265 
266  state = STATE_COMMAND_EXECUTED;
267  break;
268  }
269  // don't break parsing when the char is required for the next argument
270  breakParsing = false;
271 
272  // pop the stack and return the result to the current command arguments
273  close_out_params();
274 
275  // don't stringify the json in case of a string to avoid doublequotes
276  if (lastResult.isStr())
277  curarg = lastResult.get_str();
278  else
279  curarg = lastResult.write(2);
280 
281  // if we have a non empty result, use it as stack argument otherwise as general result
282  if (curarg.size())
283  {
284  if (stack.size())
285  add_to_current_stack(curarg);
286  else
287  strResult = curarg;
288  }
289  curarg.clear();
290  // assume eating space state
291  state = STATE_EATING_SPACES;
292  }
293  if (breakParsing)
294  break;
295  [[fallthrough]];
296  }
297  case STATE_ARGUMENT: // In or after argument
298  case STATE_EATING_SPACES_IN_ARG:
299  case STATE_EATING_SPACES_IN_BRACKETS:
300  case STATE_EATING_SPACES: // Handle runs of whitespace
301  switch(ch)
302  {
303  case '"': state = STATE_DOUBLEQUOTED; break;
304  case '\'': state = STATE_SINGLEQUOTED; break;
305  case '\\': state = STATE_ESCAPE_OUTER; break;
306  case '(': case ')': case '\n':
307  if (state == STATE_EATING_SPACES_IN_ARG)
308  throw std::runtime_error("Invalid Syntax");
309  if (state == STATE_ARGUMENT)
310  {
311  if (ch == '(' && stack.size() && stack.back().size() > 0)
312  {
313  if (nDepthInsideSensitive) {
314  ++nDepthInsideSensitive;
315  }
316  stack.push_back(std::vector<std::string>());
317  }
318 
319  // don't allow commands after executed commands on baselevel
320  if (!stack.size())
321  throw std::runtime_error("Invalid Syntax");
322 
323  add_to_current_stack(curarg);
324  curarg.clear();
325  state = STATE_EATING_SPACES_IN_BRACKETS;
326  }
327  if ((ch == ')' || ch == '\n') && stack.size() > 0)
328  {
329  if (fExecute) {
330  // Convert argument list to JSON objects in method-dependent way,
331  // and pass it along with the method name to the dispatcher.
332  UniValue params = RPCConvertValues(stack.back()[0], std::vector<std::string>(stack.back().begin() + 1, stack.back().end()));
333  std::string method = stack.back()[0];
334  std::string uri;
335 #ifdef ENABLE_WALLET
336  if (wallet_model) {
337  QByteArray encodedName = QUrl::toPercentEncoding(wallet_model->getWalletName());
338  uri = "/wallet/"+std::string(encodedName.constData(), encodedName.length());
339  }
340 #endif
341  assert(node);
342  lastResult = node->executeRpc(method, params, uri);
343  }
344 
345  state = STATE_COMMAND_EXECUTED;
346  curarg.clear();
347  }
348  break;
349  case ' ': case ',': case '\t':
350  if(state == STATE_EATING_SPACES_IN_ARG && curarg.empty() && ch == ',')
351  throw std::runtime_error("Invalid Syntax");
352 
353  else if(state == STATE_ARGUMENT) // Space ends argument
354  {
355  add_to_current_stack(curarg);
356  curarg.clear();
357  }
358  if ((state == STATE_EATING_SPACES_IN_BRACKETS || state == STATE_ARGUMENT) && ch == ',')
359  {
360  state = STATE_EATING_SPACES_IN_ARG;
361  break;
362  }
363  state = STATE_EATING_SPACES;
364  break;
365  default: curarg += ch; state = STATE_ARGUMENT;
366  }
367  break;
368  case STATE_SINGLEQUOTED: // Single-quoted string
369  switch(ch)
370  {
371  case '\'': state = STATE_ARGUMENT; break;
372  default: curarg += ch;
373  }
374  break;
375  case STATE_DOUBLEQUOTED: // Double-quoted string
376  switch(ch)
377  {
378  case '"': state = STATE_ARGUMENT; break;
379  case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break;
380  default: curarg += ch;
381  }
382  break;
383  case STATE_ESCAPE_OUTER: // '\' outside quotes
384  curarg += ch; state = STATE_ARGUMENT;
385  break;
386  case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text
387  if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself
388  curarg += ch; state = STATE_DOUBLEQUOTED;
389  break;
390  }
391  }
392  if (pstrFilteredOut) {
393  if (STATE_COMMAND_EXECUTED == state) {
394  assert(!stack.empty());
395  close_out_params();
396  }
397  *pstrFilteredOut = strCommand;
398  for (auto i = filter_ranges.rbegin(); i != filter_ranges.rend(); ++i) {
399  pstrFilteredOut->replace(i->first, i->second - i->first, "(…)");
400  }
401  }
402  switch(state) // final state
403  {
404  case STATE_COMMAND_EXECUTED:
405  if (lastResult.isStr())
406  strResult = lastResult.get_str();
407  else
408  strResult = lastResult.write(2);
409  [[fallthrough]];
410  case STATE_ARGUMENT:
411  case STATE_EATING_SPACES:
412  return true;
413  default: // ERROR to end in one of the other states
414  return false;
415  }
416 }
417 
418 void RPCExecutor::request(const QString &command, const WalletModel* wallet_model)
419 {
420  try
421  {
422  std::string result;
423  std::string executableCommand = command.toStdString() + "\n";
424 
425  // Catch the console-only-help command before RPC call is executed and reply with help text as-if a RPC reply.
426  if(executableCommand == "help-console\n") {
427  Q_EMIT reply(RPCConsole::CMD_REPLY, QString(("\n"
428  "This console accepts RPC commands using the standard syntax.\n"
429  " example: getblockhash 0\n\n"
430 
431  "This console can also accept RPC commands using the parenthesized syntax.\n"
432  " example: getblockhash(0)\n\n"
433 
434  "Commands may be nested when specified with the parenthesized syntax.\n"
435  " example: getblock(getblockhash(0) 1)\n\n"
436 
437  "A space or a comma can be used to delimit arguments for either syntax.\n"
438  " example: getblockhash 0\n"
439  " getblockhash,0\n\n"
440 
441  "Named results can be queried with a non-quoted key string in brackets using the parenthesized syntax.\n"
442  " example: getblock(getblockhash(0) 1)[tx]\n\n"
443 
444  "Results without keys can be queried with an integer in brackets using the parenthesized syntax.\n"
445  " example: getblock(getblockhash(0),1)[tx][0]\n\n")));
446  return;
447  }
448  if (!RPCConsole::RPCExecuteCommandLine(m_node, result, executableCommand, nullptr, wallet_model)) {
449  Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \""));
450  return;
451  }
452 
453  Q_EMIT reply(RPCConsole::CMD_REPLY, QString::fromStdString(result));
454  }
455  catch (UniValue& objError)
456  {
457  try // Nice formatting for standard-format error
458  {
459  int code = find_value(objError, "code").get_int();
460  std::string message = find_value(objError, "message").get_str();
461  Q_EMIT reply(RPCConsole::CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")");
462  }
463  catch (const std::runtime_error&) // raised when converting to invalid type, i.e. missing code or message
464  { // Show raw JSON object
465  Q_EMIT reply(RPCConsole::CMD_ERROR, QString::fromStdString(objError.write()));
466  }
467  }
468  catch (const std::exception& e)
469  {
470  Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what()));
471  }
472 }
473 
474 RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformStyle, QWidget *parent) :
475  QWidget(parent),
476  m_node(node),
477  ui(new Ui::RPCConsole),
478  platformStyle(_platformStyle)
479 {
480  ui->setupUi(this);
481  QSettings settings;
482 #ifdef ENABLE_WALLET
484  // RPCConsole widget is a window.
485  if (!restoreGeometry(settings.value("RPCConsoleWindowGeometry").toByteArray())) {
486  // Restore failed (perhaps missing setting), center the window
487  move(QGuiApplication::primaryScreen()->availableGeometry().center() - frameGeometry().center());
488  }
489  ui->splitter->restoreState(settings.value("RPCConsoleWindowPeersTabSplitterSizes").toByteArray());
490  } else
491 #endif // ENABLE_WALLET
492  {
493  // RPCConsole is a child widget.
494  ui->splitter->restoreState(settings.value("RPCConsoleWidgetPeersTabSplitterSizes").toByteArray());
495  }
496 
497  m_peer_widget_header_state = settings.value("PeersTabPeerHeaderState").toByteArray();
498  m_banlist_widget_header_state = settings.value("PeersTabBanlistHeaderState").toByteArray();
499 
500  constexpr QChar nonbreaking_hyphen(8209);
501  const std::vector<QString> CONNECTION_TYPE_DOC{
502  //: Explanatory text for an inbound peer connection.
503  tr("Inbound: initiated by peer"),
504  /*: Explanatory text for an outbound peer connection that
505  relays all network information. This is the default behavior for
506  outbound connections. */
507  tr("Outbound Full Relay: default"),
508  /*: Explanatory text for an outbound peer connection that relays
509  network information about blocks and not transactions or addresses. */
510  tr("Outbound Block Relay: does not relay transactions or addresses"),
511  /*: Explanatory text for an outbound peer connection that was
512  established manually through one of several methods. The numbered
513  arguments are stand-ins for the methods available to establish
514  manual connections. */
515  tr("Outbound Manual: added using RPC %1 or %2/%3 configuration options")
516  .arg("addnode")
517  .arg(QString(nonbreaking_hyphen) + "addnode")
518  .arg(QString(nonbreaking_hyphen) + "connect"),
519  /*: Explanatory text for a short-lived outbound peer connection that
520  is used to test the aliveness of known addresses. */
521  tr("Outbound Feeler: short-lived, for testing addresses"),
522  /*: Explanatory text for a short-lived outbound peer connection that is used
523  to request addresses from a peer. */
524  tr("Outbound Address Fetch: short-lived, for soliciting addresses")};
525  const QString list{"<ul><li>" + Join(CONNECTION_TYPE_DOC, QString("</li><li>")) + "</li></ul>"};
526  ui->peerConnectionTypeLabel->setToolTip(ui->peerConnectionTypeLabel->toolTip().arg(list));
527  const QString hb_list{"<ul><li>\""
528  + ts.to + "\" – " + tr("we selected the peer for high bandwidth relay") + "</li><li>\""
529  + ts.from + "\" – " + tr("the peer selected us for high bandwidth relay") + "</li><li>\""
530  + ts.no + "\" – " + tr("no high bandwidth relay selected") + "</li></ul>"};
531  ui->peerHighBandwidthLabel->setToolTip(ui->peerHighBandwidthLabel->toolTip().arg(hb_list));
532  ui->dataDir->setToolTip(ui->dataDir->toolTip().arg(QString(nonbreaking_hyphen) + "datadir"));
533  ui->blocksDir->setToolTip(ui->blocksDir->toolTip().arg(QString(nonbreaking_hyphen) + "blocksdir"));
534  ui->openDebugLogfileButton->setToolTip(ui->openDebugLogfileButton->toolTip().arg(PACKAGE_NAME));
535 
537  ui->openDebugLogfileButton->setIcon(platformStyle->SingleColorIcon(":/icons/export"));
538  }
539  ui->clearButton->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
540 
541  ui->fontBiggerButton->setIcon(platformStyle->SingleColorIcon(":/icons/fontbigger"));
542  //: Main shortcut to increase the RPC console font size.
543  ui->fontBiggerButton->setShortcut(tr("Ctrl++"));
544  //: Secondary shortcut to increase the RPC console font size.
545  GUIUtil::AddButtonShortcut(ui->fontBiggerButton, tr("Ctrl+="));
546 
547  ui->fontSmallerButton->setIcon(platformStyle->SingleColorIcon(":/icons/fontsmaller"));
548  //: Main shortcut to decrease the RPC console font size.
549  ui->fontSmallerButton->setShortcut(tr("Ctrl+-"));
550  //: Secondary shortcut to decrease the RPC console font size.
551  GUIUtil::AddButtonShortcut(ui->fontSmallerButton, tr("Ctrl+_"));
552 
553  ui->promptIcon->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/prompticon")));
554 
555  // Install event filter for up and down arrow
556  ui->lineEdit->installEventFilter(this);
557  ui->lineEdit->setMaxLength(16 * 1024 * 1024);
558  ui->messagesWidget->installEventFilter(this);
559 
560  connect(ui->clearButton, &QAbstractButton::clicked, [this] { clear(); });
561  connect(ui->fontBiggerButton, &QAbstractButton::clicked, this, &RPCConsole::fontBigger);
562  connect(ui->fontSmallerButton, &QAbstractButton::clicked, this, &RPCConsole::fontSmaller);
563  connect(ui->btnClearTrafficGraph, &QPushButton::clicked, ui->trafficGraph, &TrafficGraphWidget::clear);
564 
565  // disable the wallet selector by default
566  ui->WalletSelector->setVisible(false);
567  ui->WalletSelectorLabel->setVisible(false);
568 
569  // Register RPC timer interface
571  // avoid accidentally overwriting an existing, non QTThread
572  // based timer interface
574 
577 
578  consoleFontSize = settings.value(fontSizeSettingsKey, QFont().pointSize()).toInt();
579  clear();
580 
582 }
583 
585 {
586  QSettings settings;
587 #ifdef ENABLE_WALLET
589  // RPCConsole widget is a window.
590  settings.setValue("RPCConsoleWindowGeometry", saveGeometry());
591  settings.setValue("RPCConsoleWindowPeersTabSplitterSizes", ui->splitter->saveState());
592  } else
593 #endif // ENABLE_WALLET
594  {
595  // RPCConsole is a child widget.
596  settings.setValue("RPCConsoleWidgetPeersTabSplitterSizes", ui->splitter->saveState());
597  }
598 
599  settings.setValue("PeersTabPeerHeaderState", m_peer_widget_header_state);
600  settings.setValue("PeersTabBanlistHeaderState", m_banlist_widget_header_state);
601 
603  delete rpcTimerInterface;
604  delete ui;
605 }
606 
607 bool RPCConsole::eventFilter(QObject* obj, QEvent *event)
608 {
609  if(event->type() == QEvent::KeyPress) // Special key handling
610  {
611  QKeyEvent *keyevt = static_cast<QKeyEvent*>(event);
612  int key = keyevt->key();
613  Qt::KeyboardModifiers mod = keyevt->modifiers();
614  switch(key)
615  {
616  case Qt::Key_Up: if(obj == ui->lineEdit) { browseHistory(-1); return true; } break;
617  case Qt::Key_Down: if(obj == ui->lineEdit) { browseHistory(1); return true; } break;
618  case Qt::Key_PageUp: /* pass paging keys to messages widget */
619  case Qt::Key_PageDown:
620  if(obj == ui->lineEdit)
621  {
622  QApplication::postEvent(ui->messagesWidget, new QKeyEvent(*keyevt));
623  return true;
624  }
625  break;
626  case Qt::Key_Return:
627  case Qt::Key_Enter:
628  // forward these events to lineEdit
629  if(obj == autoCompleter->popup()) {
630  QApplication::postEvent(ui->lineEdit, new QKeyEvent(*keyevt));
631  autoCompleter->popup()->hide();
632  return true;
633  }
634  break;
635  default:
636  // Typing in messages widget brings focus to line edit, and redirects key there
637  // Exclude most combinations and keys that emit no text, except paste shortcuts
638  if(obj == ui->messagesWidget && (
639  (!mod && !keyevt->text().isEmpty() && key != Qt::Key_Tab) ||
640  ((mod & Qt::ControlModifier) && key == Qt::Key_V) ||
641  ((mod & Qt::ShiftModifier) && key == Qt::Key_Insert)))
642  {
643  ui->lineEdit->setFocus();
644  QApplication::postEvent(ui->lineEdit, new QKeyEvent(*keyevt));
645  return true;
646  }
647  }
648  }
649  return QWidget::eventFilter(obj, event);
650 }
651 
652 void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_t bestblock_date, double verification_progress)
653 {
654  clientModel = model;
655 
656  bool wallet_enabled{false};
657 #ifdef ENABLE_WALLET
658  wallet_enabled = WalletModel::isWalletEnabled();
659 #endif // ENABLE_WALLET
660  if (model && !wallet_enabled) {
661  // Show warning, for example if this is a prerelease version
662  connect(model, &ClientModel::alertsChanged, this, &RPCConsole::updateAlerts);
664  }
665 
666  ui->trafficGraph->setClientModel(model);
668  // Keep up to date with client
671 
672  setNumBlocks(bestblock_height, QDateTime::fromSecsSinceEpoch(bestblock_date), verification_progress, false);
674 
677 
679  updateTrafficStats(node.getTotalBytesRecv(), node.getTotalBytesSent());
681 
683 
684  // set up peer table
685  ui->peerWidget->setModel(model->peerTableSortProxy());
686  ui->peerWidget->verticalHeader()->hide();
687  ui->peerWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
688  ui->peerWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
689  ui->peerWidget->setContextMenuPolicy(Qt::CustomContextMenu);
690 
691  if (!ui->peerWidget->horizontalHeader()->restoreState(m_peer_widget_header_state)) {
692  ui->peerWidget->setColumnWidth(PeerTableModel::Address, ADDRESS_COLUMN_WIDTH);
693  ui->peerWidget->setColumnWidth(PeerTableModel::Subversion, SUBVERSION_COLUMN_WIDTH);
694  ui->peerWidget->setColumnWidth(PeerTableModel::Ping, PING_COLUMN_WIDTH);
695  }
696  ui->peerWidget->horizontalHeader()->setStretchLastSection(true);
697  ui->peerWidget->setItemDelegateForColumn(PeerTableModel::NetNodeId, new PeerIdViewDelegate(this));
698 
699  // create peer table context menu
700  peersTableContextMenu = new QMenu(this);
701  //: Context menu action to copy the address of a peer.
702  peersTableContextMenu->addAction(tr("&Copy address"), [this] {
703  GUIUtil::copyEntryData(ui->peerWidget, PeerTableModel::Address, Qt::DisplayRole);
704  });
705  peersTableContextMenu->addSeparator();
706  peersTableContextMenu->addAction(tr("&Disconnect"), this, &RPCConsole::disconnectSelectedNode);
707  peersTableContextMenu->addAction(ts.ban_for + " " + tr("1 &hour"), [this] { banSelectedNode(60 * 60); });
708  peersTableContextMenu->addAction(ts.ban_for + " " + tr("1 d&ay"), [this] { banSelectedNode(60 * 60 * 24); });
709  peersTableContextMenu->addAction(ts.ban_for + " " + tr("1 &week"), [this] { banSelectedNode(60 * 60 * 24 * 7); });
710  peersTableContextMenu->addAction(ts.ban_for + " " + tr("1 &year"), [this] { banSelectedNode(60 * 60 * 24 * 365); });
711  connect(ui->peerWidget, &QTableView::customContextMenuRequested, this, &RPCConsole::showPeersTableContextMenu);
712 
713  // peer table signal handling - update peer details when selecting new node
714  connect(ui->peerWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, &RPCConsole::updateDetailWidget);
715  connect(model->getPeerTableModel(), &QAbstractItemModel::dataChanged, [this] { updateDetailWidget(); });
716 
717  // set up ban table
718  ui->banlistWidget->setModel(model->getBanTableModel());
719  ui->banlistWidget->verticalHeader()->hide();
720  ui->banlistWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
721  ui->banlistWidget->setSelectionMode(QAbstractItemView::SingleSelection);
722  ui->banlistWidget->setContextMenuPolicy(Qt::CustomContextMenu);
723 
724  if (!ui->banlistWidget->horizontalHeader()->restoreState(m_banlist_widget_header_state)) {
725  ui->banlistWidget->setColumnWidth(BanTableModel::Address, BANSUBNET_COLUMN_WIDTH);
726  ui->banlistWidget->setColumnWidth(BanTableModel::Bantime, BANTIME_COLUMN_WIDTH);
727  }
728  ui->banlistWidget->horizontalHeader()->setStretchLastSection(true);
729 
730  // create ban table context menu
731  banTableContextMenu = new QMenu(this);
732  /*: Context menu action to copy the IP/Netmask of a banned peer.
733  IP/Netmask is the combination of a peer's IP address and its Netmask.
734  For IP address, see: https://en.wikipedia.org/wiki/IP_address. */
735  banTableContextMenu->addAction(tr("&Copy IP/Netmask"), [this] {
736  GUIUtil::copyEntryData(ui->banlistWidget, BanTableModel::Address, Qt::DisplayRole);
737  });
738  banTableContextMenu->addSeparator();
739  banTableContextMenu->addAction(tr("&Unban"), this, &RPCConsole::unbanSelectedNode);
740  connect(ui->banlistWidget, &QTableView::customContextMenuRequested, this, &RPCConsole::showBanTableContextMenu);
741 
742  // ban table signal handling - clear peer details when clicking a peer in the ban table
743  connect(ui->banlistWidget, &QTableView::clicked, this, &RPCConsole::clearSelectedNode);
744  // ban table signal handling - ensure ban table is shown or hidden (if empty)
745  connect(model->getBanTableModel(), &BanTableModel::layoutChanged, this, &RPCConsole::showOrHideBanTableIfRequired);
747 
748  // Provide initial values
749  ui->clientVersion->setText(model->formatFullVersion());
750  ui->clientUserAgent->setText(model->formatSubVersion());
751  ui->dataDir->setText(model->dataDir());
752  ui->blocksDir->setText(model->blocksDir());
753  ui->startupTime->setText(model->formatClientStartupTime());
754  ui->networkName->setText(QString::fromStdString(Params().NetworkIDString()));
755 
756  //Setup autocomplete and attach it
757  QStringList wordList;
758  std::vector<std::string> commandList = m_node.listRpcCommands();
759  for (size_t i = 0; i < commandList.size(); ++i)
760  {
761  wordList << commandList[i].c_str();
762  wordList << ("help " + commandList[i]).c_str();
763  }
764 
765  wordList << "help-console";
766  wordList.sort();
767  autoCompleter = new QCompleter(wordList, this);
768  autoCompleter->setModelSorting(QCompleter::CaseSensitivelySortedModel);
769  // ui->lineEdit is initially disabled because running commands is only
770  // possible from now on.
771  ui->lineEdit->setEnabled(true);
772  ui->lineEdit->setCompleter(autoCompleter);
773  autoCompleter->popup()->installEventFilter(this);
774  // Start thread to execute RPC commands.
775  startExecutor();
776  }
777  if (!model) {
778  // Client model is being set to 0, this means shutdown() is about to be called.
779  thread.quit();
780  thread.wait();
781  }
782 }
783 
784 #ifdef ENABLE_WALLET
785 void RPCConsole::addWallet(WalletModel * const walletModel)
786 {
787  // use name for text and wallet model for internal data object (to allow to move to a wallet id later)
788  ui->WalletSelector->addItem(walletModel->getDisplayName(), QVariant::fromValue(walletModel));
789  if (ui->WalletSelector->count() == 2 && !isVisible()) {
790  // First wallet added, set to default so long as the window isn't presently visible (and potentially in use)
791  ui->WalletSelector->setCurrentIndex(1);
792  }
793  if (ui->WalletSelector->count() > 2) {
794  ui->WalletSelector->setVisible(true);
795  ui->WalletSelectorLabel->setVisible(true);
796  }
797 }
798 
799 void RPCConsole::removeWallet(WalletModel * const walletModel)
800 {
801  ui->WalletSelector->removeItem(ui->WalletSelector->findData(QVariant::fromValue(walletModel)));
802  if (ui->WalletSelector->count() == 2) {
803  ui->WalletSelector->setVisible(false);
804  ui->WalletSelectorLabel->setVisible(false);
805  }
806 }
807 #endif
808 
809 static QString categoryClass(int category)
810 {
811  switch(category)
812  {
813  case RPCConsole::CMD_REQUEST: return "cmd-request"; break;
814  case RPCConsole::CMD_REPLY: return "cmd-reply"; break;
815  case RPCConsole::CMD_ERROR: return "cmd-error"; break;
816  default: return "misc";
817  }
818 }
819 
821 {
823 }
824 
826 {
828 }
829 
830 void RPCConsole::setFontSize(int newSize)
831 {
832  QSettings settings;
833 
834  //don't allow an insane font size
835  if (newSize < FONT_RANGE.width() || newSize > FONT_RANGE.height())
836  return;
837 
838  // temp. store the console content
839  QString str = ui->messagesWidget->toHtml();
840 
841  // replace font tags size in current content
842  str.replace(QString("font-size:%1pt").arg(consoleFontSize), QString("font-size:%1pt").arg(newSize));
843 
844  // store the new font size
845  consoleFontSize = newSize;
846  settings.setValue(fontSizeSettingsKey, consoleFontSize);
847 
848  // clear console (reset icon sizes, default stylesheet) and re-add the content
849  float oldPosFactor = 1.0 / ui->messagesWidget->verticalScrollBar()->maximum() * ui->messagesWidget->verticalScrollBar()->value();
850  clear(/* keep_prompt */ true);
851  ui->messagesWidget->setHtml(str);
852  ui->messagesWidget->verticalScrollBar()->setValue(oldPosFactor * ui->messagesWidget->verticalScrollBar()->maximum());
853 }
854 
855 void RPCConsole::clear(bool keep_prompt)
856 {
857  ui->messagesWidget->clear();
858  if (!keep_prompt) ui->lineEdit->clear();
859  ui->lineEdit->setFocus();
860 
861  // Add smoothly scaled icon images.
862  // (when using width/height on an img, Qt uses nearest instead of linear interpolation)
863  for(int i=0; ICON_MAPPING[i].url; ++i)
864  {
865  ui->messagesWidget->document()->addResource(
866  QTextDocument::ImageResource,
867  QUrl(ICON_MAPPING[i].url),
868  platformStyle->SingleColorImage(ICON_MAPPING[i].source).scaled(QSize(consoleFontSize*2, consoleFontSize*2), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
869  }
870 
871  // Set default style sheet
872 #ifdef Q_OS_MAC
873  QFontInfo fixedFontInfo(GUIUtil::fixedPitchFont(/*use_embedded_font=*/true));
874 #else
875  QFontInfo fixedFontInfo(GUIUtil::fixedPitchFont());
876 #endif
877  ui->messagesWidget->document()->setDefaultStyleSheet(
878  QString(
879  "table { }"
880  "td.time { color: #808080; font-size: %2; padding-top: 3px; } "
881  "td.message { font-family: %1; font-size: %2; white-space:pre-wrap; } "
882  "td.cmd-request { color: #006060; } "
883  "td.cmd-error { color: red; } "
884  ".secwarning { color: red; }"
885  "b { color: #006060; } "
886  ).arg(fixedFontInfo.family(), QString("%1pt").arg(consoleFontSize))
887  );
888 
889  static const QString welcome_message =
890  /*: RPC console welcome message.
891  Placeholders %7 and %8 are style tags for the warning content, and
892  they are not space separated from the rest of the text intentionally. */
893  tr("Welcome to the %1 RPC console.\n"
894  "Use up and down arrows to navigate history, and %2 to clear screen.\n"
895  "Use %3 and %4 to increase or decrease the font size.\n"
896  "Type %5 for an overview of available commands.\n"
897  "For more information on using this console, type %6.\n"
898  "\n"
899  "%7WARNING: Scammers have been active, telling users to type"
900  " commands here, stealing their wallet contents. Do not use this console"
901  " without fully understanding the ramifications of a command.%8")
902  .arg(PACKAGE_NAME,
903  "<b>" + ui->clearButton->shortcut().toString(QKeySequence::NativeText) + "</b>",
904  "<b>" + ui->fontBiggerButton->shortcut().toString(QKeySequence::NativeText) + "</b>",
905  "<b>" + ui->fontSmallerButton->shortcut().toString(QKeySequence::NativeText) + "</b>",
906  "<b>help</b>",
907  "<b>help-console</b>",
908  "<span class=\"secwarning\">",
909  "<span>");
910 
911  message(CMD_REPLY, welcome_message, true);
912 }
913 
914 void RPCConsole::keyPressEvent(QKeyEvent *event)
915 {
916  if (windowType() != Qt::Widget && GUIUtil::IsEscapeOrBack(event->key())) {
917  close();
918  }
919 }
920 
921 void RPCConsole::changeEvent(QEvent* e)
922 {
923  if (e->type() == QEvent::PaletteChange) {
924  ui->clearButton->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/remove")));
925  ui->fontBiggerButton->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/fontbigger")));
926  ui->fontSmallerButton->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/fontsmaller")));
927  ui->promptIcon->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/prompticon")));
928 
929  for (int i = 0; ICON_MAPPING[i].url; ++i) {
930  ui->messagesWidget->document()->addResource(
931  QTextDocument::ImageResource,
932  QUrl(ICON_MAPPING[i].url),
933  platformStyle->SingleColorImage(ICON_MAPPING[i].source).scaled(QSize(consoleFontSize * 2, consoleFontSize * 2), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
934  }
935  }
936 
937  QWidget::changeEvent(e);
938 }
939 
940 void RPCConsole::message(int category, const QString &message, bool html)
941 {
942  QTime time = QTime::currentTime();
943  QString timeString = time.toString();
944  QString out;
945  out += "<table><tr><td class=\"time\" width=\"65\">" + timeString + "</td>";
946  out += "<td class=\"icon\" width=\"32\"><img src=\"" + categoryClass(category) + "\"></td>";
947  out += "<td class=\"message " + categoryClass(category) + "\" valign=\"middle\">";
948  if(html)
949  out += message;
950  else
951  out += GUIUtil::HtmlEscape(message, false);
952  out += "</td></tr></table>";
953  ui->messagesWidget->append(out);
954 }
955 
957 {
958  QString connections = QString::number(clientModel->getNumConnections()) + " (";
959  connections += tr("In:") + " " + QString::number(clientModel->getNumConnections(CONNECTIONS_IN)) + " / ";
960  connections += tr("Out:") + " " + QString::number(clientModel->getNumConnections(CONNECTIONS_OUT)) + ")";
961 
962  if(!clientModel->node().getNetworkActive()) {
963  connections += " (" + tr("Network activity disabled") + ")";
964  }
965 
966  ui->numberOfConnections->setText(connections);
967 }
968 
970 {
971  if (!clientModel)
972  return;
973 
975 }
976 
977 void RPCConsole::setNetworkActive(bool networkActive)
978 {
980 }
981 
982 void RPCConsole::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers)
983 {
984  if (!headers) {
985  ui->numberOfBlocks->setText(QString::number(count));
986  ui->lastBlockTime->setText(blockDate.toString());
987  }
988 }
989 
990 void RPCConsole::setMempoolSize(long numberOfTxs, size_t dynUsage)
991 {
992  ui->mempoolNumberTxs->setText(QString::number(numberOfTxs));
993 
994  if (dynUsage < 1000000)
995  ui->mempoolSize->setText(QString::number(dynUsage/1000.0, 'f', 2) + " KB");
996  else
997  ui->mempoolSize->setText(QString::number(dynUsage/1000000.0, 'f', 2) + " MB");
998 }
999 
1001 {
1002  QString cmd = ui->lineEdit->text().trimmed();
1003 
1004  if (cmd.isEmpty()) {
1005  return;
1006  }
1007 
1008  std::string strFilteredCmd;
1009  try {
1010  std::string dummy;
1011  if (!RPCParseCommandLine(nullptr, dummy, cmd.toStdString(), false, &strFilteredCmd)) {
1012  // Failed to parse command, so we cannot even filter it for the history
1013  throw std::runtime_error("Invalid command line");
1014  }
1015  } catch (const std::exception& e) {
1016  QMessageBox::critical(this, "Error", QString("Error: ") + QString::fromStdString(e.what()));
1017  return;
1018  }
1019 
1020  // A special case allows to request shutdown even a long-running command is executed.
1021  if (cmd == QLatin1String("stop")) {
1022  std::string dummy;
1023  RPCExecuteCommandLine(m_node, dummy, cmd.toStdString());
1024  return;
1025  }
1026 
1027  if (m_is_executing) {
1028  return;
1029  }
1030 
1031  ui->lineEdit->clear();
1032 
1033 #ifdef ENABLE_WALLET
1034  WalletModel* wallet_model = ui->WalletSelector->currentData().value<WalletModel*>();
1035 
1036  if (m_last_wallet_model != wallet_model) {
1037  if (wallet_model) {
1038  message(CMD_REQUEST, tr("Executing command using \"%1\" wallet").arg(wallet_model->getWalletName()));
1039  } else {
1040  message(CMD_REQUEST, tr("Executing command without any wallet"));
1041  }
1042  m_last_wallet_model = wallet_model;
1043  }
1044 #endif // ENABLE_WALLET
1045 
1046  message(CMD_REQUEST, QString::fromStdString(strFilteredCmd));
1047  //: A console message indicating an entered command is currently being executed.
1048  message(CMD_REPLY, tr("Executing…"));
1049  m_is_executing = true;
1050  Q_EMIT cmdRequest(cmd, m_last_wallet_model);
1051 
1052  cmd = QString::fromStdString(strFilteredCmd);
1053 
1054  // Remove command, if already in history
1055  history.removeOne(cmd);
1056  // Append command to history
1057  history.append(cmd);
1058  // Enforce maximum history size
1059  while (history.size() > CONSOLE_HISTORY) {
1060  history.removeFirst();
1061  }
1062  // Set pointer to end of history
1063  historyPtr = history.size();
1064 
1065  // Scroll console view to end
1066  scrollToEnd();
1067 }
1068 
1070 {
1071  // store current text when start browsing through the history
1072  if (historyPtr == history.size()) {
1073  cmdBeforeBrowsing = ui->lineEdit->text();
1074  }
1075 
1076  historyPtr += offset;
1077  if(historyPtr < 0)
1078  historyPtr = 0;
1079  if(historyPtr > history.size())
1080  historyPtr = history.size();
1081  QString cmd;
1082  if(historyPtr < history.size())
1083  cmd = history.at(historyPtr);
1084  else if (!cmdBeforeBrowsing.isNull()) {
1085  cmd = cmdBeforeBrowsing;
1086  }
1087  ui->lineEdit->setText(cmd);
1088 }
1089 
1091 {
1092  RPCExecutor *executor = new RPCExecutor(m_node);
1093  executor->moveToThread(&thread);
1094 
1095  // Replies from executor object must go to this object
1096  connect(executor, &RPCExecutor::reply, this, [this](int category, const QString& command) {
1097  // Remove "Executing…" message.
1098  ui->messagesWidget->undo();
1099  message(category, command);
1100  scrollToEnd();
1101  m_is_executing = false;
1102  });
1103 
1104  // Requests from this object must go to executor
1105  connect(this, &RPCConsole::cmdRequest, executor, &RPCExecutor::request);
1106 
1107  // Make sure executor object is deleted in its own thread
1108  connect(&thread, &QThread::finished, executor, &RPCExecutor::deleteLater);
1109 
1110  // Default implementation of QThread::run() simply spins up an event loop in the thread,
1111  // which is what we want.
1112  thread.start();
1113  QTimer::singleShot(0, executor, []() {
1114  util::ThreadRename("qt-rpcconsole");
1115  });
1116 }
1117 
1119 {
1120  if (ui->tabWidget->widget(index) == ui->tab_console) {
1121  ui->lineEdit->setFocus();
1122  }
1123 }
1124 
1126 {
1128 }
1129 
1131 {
1132  QScrollBar *scrollbar = ui->messagesWidget->verticalScrollBar();
1133  scrollbar->setValue(scrollbar->maximum());
1134 }
1135 
1137 {
1138  const int multiplier = 5; // each position on the slider represents 5 min
1139  int mins = value * multiplier;
1140  setTrafficGraphRange(mins);
1141 }
1142 
1144 {
1145  ui->trafficGraph->setGraphRange(std::chrono::minutes{mins});
1146  ui->lblGraphRange->setText(GUIUtil::formatDurationStr(std::chrono::minutes{mins}));
1147 }
1148 
1149 void RPCConsole::updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut)
1150 {
1151  ui->lblBytesIn->setText(GUIUtil::formatBytes(totalBytesIn));
1152  ui->lblBytesOut->setText(GUIUtil::formatBytes(totalBytesOut));
1153 }
1154 
1156 {
1157  const QList<QModelIndex> selected_peers = GUIUtil::getEntryData(ui->peerWidget, PeerTableModel::NetNodeId);
1158  if (!clientModel || !clientModel->getPeerTableModel() || selected_peers.size() != 1) {
1159  ui->peersTabRightPanel->hide();
1160  ui->peerHeading->setText(tr("Select a peer to view detailed information."));
1161  return;
1162  }
1163  const auto stats = selected_peers.first().data(PeerTableModel::StatsRole).value<CNodeCombinedStats*>();
1164  // update the detail ui with latest node information
1165  QString peerAddrDetails(QString::fromStdString(stats->nodeStats.m_addr_name) + " ");
1166  peerAddrDetails += tr("(peer: %1)").arg(QString::number(stats->nodeStats.nodeid));
1167  if (!stats->nodeStats.addrLocal.empty())
1168  peerAddrDetails += "<br />" + tr("via %1").arg(QString::fromStdString(stats->nodeStats.addrLocal));
1169  ui->peerHeading->setText(peerAddrDetails);
1170  ui->peerServices->setText(GUIUtil::formatServicesStr(stats->nodeStats.nServices));
1171  ui->peerRelayTxes->setText(stats->nodeStats.fRelayTxes ? ts.yes : ts.no);
1172  QString bip152_hb_settings;
1173  if (stats->nodeStats.m_bip152_highbandwidth_to) bip152_hb_settings = ts.to;
1174  if (stats->nodeStats.m_bip152_highbandwidth_from) bip152_hb_settings += (bip152_hb_settings.isEmpty() ? ts.from : QLatin1Char('/') + ts.from);
1175  if (bip152_hb_settings.isEmpty()) bip152_hb_settings = ts.no;
1176  ui->peerHighBandwidth->setText(bip152_hb_settings);
1177  const auto time_now{GetTime<std::chrono::seconds>()};
1178  ui->peerConnTime->setText(GUIUtil::formatDurationStr(time_now - stats->nodeStats.m_connected));
1179  ui->peerLastBlock->setText(TimeDurationField(time_now, stats->nodeStats.m_last_block_time));
1180  ui->peerLastTx->setText(TimeDurationField(time_now, stats->nodeStats.m_last_tx_time));
1181  ui->peerLastSend->setText(TimeDurationField(time_now, stats->nodeStats.m_last_send));
1182  ui->peerLastRecv->setText(TimeDurationField(time_now, stats->nodeStats.m_last_recv));
1183  ui->peerBytesSent->setText(GUIUtil::formatBytes(stats->nodeStats.nSendBytes));
1184  ui->peerBytesRecv->setText(GUIUtil::formatBytes(stats->nodeStats.nRecvBytes));
1185  ui->peerPingTime->setText(GUIUtil::formatPingTime(stats->nodeStats.m_last_ping_time));
1186  ui->peerMinPing->setText(GUIUtil::formatPingTime(stats->nodeStats.m_min_ping_time));
1187  ui->timeoffset->setText(GUIUtil::formatTimeOffset(stats->nodeStats.nTimeOffset));
1188  ui->peerVersion->setText(QString::number(stats->nodeStats.nVersion));
1189  ui->peerSubversion->setText(QString::fromStdString(stats->nodeStats.cleanSubVer));
1190  ui->peerConnectionType->setText(GUIUtil::ConnectionTypeToQString(stats->nodeStats.m_conn_type, /* prepend_direction */ true));
1191  ui->peerNetwork->setText(GUIUtil::NetworkToQString(stats->nodeStats.m_network));
1192  if (stats->nodeStats.m_permissionFlags == NetPermissionFlags::None) {
1193  ui->peerPermissions->setText(ts.na);
1194  } else {
1195  QStringList permissions;
1196  for (const auto& permission : NetPermissions::ToStrings(stats->nodeStats.m_permissionFlags)) {
1197  permissions.append(QString::fromStdString(permission));
1198  }
1199  ui->peerPermissions->setText(permissions.join(" & "));
1200  }
1201  ui->peerMappedAS->setText(stats->nodeStats.m_mapped_as != 0 ? QString::number(stats->nodeStats.m_mapped_as) : ts.na);
1202 
1203  // This check fails for example if the lock was busy and
1204  // nodeStateStats couldn't be fetched.
1205  if (stats->fNodeStateStatsAvailable) {
1206  // Sync height is init to -1
1207  if (stats->nodeStateStats.nSyncHeight > -1) {
1208  ui->peerSyncHeight->setText(QString("%1").arg(stats->nodeStateStats.nSyncHeight));
1209  } else {
1210  ui->peerSyncHeight->setText(ts.unknown);
1211  }
1212  // Common height is init to -1
1213  if (stats->nodeStateStats.nCommonHeight > -1) {
1214  ui->peerCommonHeight->setText(QString("%1").arg(stats->nodeStateStats.nCommonHeight));
1215  } else {
1216  ui->peerCommonHeight->setText(ts.unknown);
1217  }
1218  ui->peerHeight->setText(QString::number(stats->nodeStateStats.m_starting_height));
1219  ui->peerPingWait->setText(GUIUtil::formatPingTime(stats->nodeStateStats.m_ping_wait));
1220  ui->peerAddrRelayEnabled->setText(stats->nodeStateStats.m_addr_relay_enabled ? ts.yes : ts.no);
1221  ui->peerAddrProcessed->setText(QString::number(stats->nodeStateStats.m_addr_processed));
1222  ui->peerAddrRateLimited->setText(QString::number(stats->nodeStateStats.m_addr_rate_limited));
1223  }
1224 
1225  ui->peersTabRightPanel->show();
1226 }
1227 
1228 void RPCConsole::resizeEvent(QResizeEvent *event)
1229 {
1230  QWidget::resizeEvent(event);
1231 }
1232 
1233 void RPCConsole::showEvent(QShowEvent *event)
1234 {
1235  QWidget::showEvent(event);
1236 
1238  return;
1239 
1240  // start PeerTableModel auto refresh
1242 }
1243 
1244 void RPCConsole::hideEvent(QHideEvent *event)
1245 {
1246  // It is too late to call QHeaderView::saveState() in ~RPCConsole(), as all of
1247  // the columns of QTableView child widgets will have zero width at that moment.
1248  m_peer_widget_header_state = ui->peerWidget->horizontalHeader()->saveState();
1249  m_banlist_widget_header_state = ui->banlistWidget->horizontalHeader()->saveState();
1250 
1251  QWidget::hideEvent(event);
1252 
1254  return;
1255 
1256  // stop PeerTableModel auto refresh
1258 }
1259 
1260 void RPCConsole::showPeersTableContextMenu(const QPoint& point)
1261 {
1262  QModelIndex index = ui->peerWidget->indexAt(point);
1263  if (index.isValid())
1264  peersTableContextMenu->exec(QCursor::pos());
1265 }
1266 
1267 void RPCConsole::showBanTableContextMenu(const QPoint& point)
1268 {
1269  QModelIndex index = ui->banlistWidget->indexAt(point);
1270  if (index.isValid())
1271  banTableContextMenu->exec(QCursor::pos());
1272 }
1273 
1275 {
1276  // Get selected peer addresses
1277  QList<QModelIndex> nodes = GUIUtil::getEntryData(ui->peerWidget, PeerTableModel::NetNodeId);
1278  for(int i = 0; i < nodes.count(); i++)
1279  {
1280  // Get currently selected peer address
1281  NodeId id = nodes.at(i).data().toLongLong();
1282  // Find the node, disconnect it and clear the selected node
1283  if(m_node.disconnectById(id))
1285  }
1286 }
1287 
1289 {
1290  if (!clientModel)
1291  return;
1292 
1293  for (const QModelIndex& peer : GUIUtil::getEntryData(ui->peerWidget, PeerTableModel::NetNodeId)) {
1294  // Find possible nodes, ban it and clear the selected node
1295  const auto stats = peer.data(PeerTableModel::StatsRole).value<CNodeCombinedStats*>();
1296  if (stats) {
1297  m_node.ban(stats->nodeStats.addr, bantime);
1298  m_node.disconnectByAddress(stats->nodeStats.addr);
1299  }
1300  }
1303 }
1304 
1306 {
1307  if (!clientModel)
1308  return;
1309 
1310  // Get selected ban addresses
1311  QList<QModelIndex> nodes = GUIUtil::getEntryData(ui->banlistWidget, BanTableModel::Address);
1312  for(int i = 0; i < nodes.count(); i++)
1313  {
1314  // Get currently selected ban address
1315  QString strNode = nodes.at(i).data().toString();
1316  CSubNet possibleSubnet;
1317 
1318  LookupSubNet(strNode.toStdString(), possibleSubnet);
1319  if (possibleSubnet.IsValid() && m_node.unban(possibleSubnet))
1320  {
1322  }
1323  }
1324 }
1325 
1327 {
1328  ui->peerWidget->selectionModel()->clearSelection();
1329  cachedNodeids.clear();
1331 }
1332 
1334 {
1335  if (!clientModel)
1336  return;
1337 
1338  bool visible = clientModel->getBanTableModel()->shouldShow();
1339  ui->banlistWidget->setVisible(visible);
1340  ui->banHeading->setVisible(visible);
1341 }
1342 
1344 {
1345  ui->tabWidget->setCurrentIndex(int(tabType));
1346 }
1347 
1348 QString RPCConsole::tabTitle(TabTypes tab_type) const
1349 {
1350  return ui->tabWidget->tabText(int(tab_type));
1351 }
1352 
1353 QKeySequence RPCConsole::tabShortcut(TabTypes tab_type) const
1354 {
1355  switch (tab_type) {
1356  case TabTypes::INFO: return QKeySequence(Qt::CTRL + Qt::Key_I);
1357  case TabTypes::CONSOLE: return QKeySequence(Qt::CTRL + Qt::Key_T);
1358  case TabTypes::GRAPH: return QKeySequence(Qt::CTRL + Qt::Key_N);
1359  case TabTypes::PEERS: return QKeySequence(Qt::CTRL + Qt::Key_P);
1360  } // no default case, so the compiler can warn about missing cases
1361 
1362  assert(false);
1363 }
1364 
1365 void RPCConsole::updateAlerts(const QString& warnings)
1366 {
1367  this->ui->label_alerts->setVisible(!warnings.isEmpty());
1368  this->ui->label_alerts->setText(warnings);
1369 }
interfaces::Node::ban
virtual bool ban(const CNetAddr &net_addr, int64_t ban_time_offset)=0
Ban node.
RPCConsole::TabTypes::CONSOLE
@ CONSOLE
ClientModel::alertsChanged
void alertsChanged(const QString &warnings)
RPCExecutor::RPCExecutor
RPCExecutor(interfaces::Node &node)
Definition: rpcconsole.cpp:96
NodeId
int64_t NodeId
Definition: net.h:88
ClientModel::numBlocksChanged
void numBlocksChanged(int count, const QDateTime &blockDate, double nVerificationProgress, bool header, SynchronizationState sync_state)
PeerIdViewDelegate::displayText
QString displayText(const QVariant &value, const QLocale &locale) const override
Definition: rpcconsole.cpp:146
RPCConsole::TranslatedStrings::yes
const QString yes
Definition: rpcconsole.h:138
CONNECTIONS_IN
@ CONNECTIONS_IN
Definition: clientmodel.h:41
RPCConsole::setNumConnections
void setNumConnections(int count)
Set number of connections shown in the UI.
Definition: rpcconsole.cpp:969
count
static int count
Definition: tests.c:31
assert
assert(!tx.IsCoinBase())
ClientModel::numConnectionsChanged
void numConnectionsChanged(int count)
RPCConsole::ADDRESS_COLUMN_WIDTH
@ ADDRESS_COLUMN_WIDTH
Definition: rpcconsole.h:147
CONNECTIONS_OUT
@ CONNECTIONS_OUT
Definition: clientmodel.h:42
RPCConsole::TranslatedStrings::from
const QString from
Definition: rpcconsole.h:138
NetPermissionFlags::None
@ None
fontSizeSettingsKey
const char fontSizeSettingsKey[]
Definition: rpcconsole.cpp:62
ClientModel::mempoolSizeChanged
void mempoolSizeChanged(long count, size_t mempoolSizeInBytes)
PeerTableModel::NetNodeId
@ NetNodeId
Definition: peertablemodel.h:49
wallet.h
NetPermissions::ToStrings
static std::vector< std::string > ToStrings(NetPermissionFlags flags)
Definition: net_permissions.cpp:71
interfaces::Node::getNetworkActive
virtual bool getNetworkActive()=0
Get network active.
WalletModel
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:52
QtRPCTimerBase
Class for handling RPC timers (used for e.g.
Definition: rpcconsole.cpp:111
ClientModel::getNumConnections
int getNumConnections(unsigned int flags=CONNECTIONS_ALL) const
Return number of connections, default is in- and outbound (total)
Definition: clientmodel.cpp:78
RPCConsole::startExecutor
void startExecutor()
Definition: rpcconsole.cpp:1090
RPCTimerInterface
RPC timer "driver".
Definition: server.h:59
PlatformStyle::SingleColorIcon
QIcon SingleColorIcon(const QString &filename) const
Colorize an icon (given filename) with the icon color.
Definition: platformstyle.cpp:105
interfaces::Node::disconnectById
virtual bool disconnectById(NodeId id)=0
Disconnect node by id.
RPCConsole::m_peer_widget_header_state
QByteArray m_peer_widget_header_state
Definition: rpcconsole.h:171
walletmodel.h
RPCConsole::resizeEvent
void resizeEvent(QResizeEvent *event) override
Definition: rpcconsole.cpp:1228
RPCConsole::clearSelectedNode
void clearSelectedNode()
clear the selected node
Definition: rpcconsole.cpp:1326
INITIAL_TRAFFIC_GRAPH_MINS
const int INITIAL_TRAFFIC_GRAPH_MINS
Definition: rpcconsole.cpp:60
string.h
RPCConsole::TranslatedStrings::ban_for
const QString ban_for
Definition: rpcconsole.h:139
source
const char * source
Definition: rpcconsole.cpp:66
WalletModel::isWalletEnabled
static bool isWalletEnabled()
Definition: walletmodel.cpp:572
RPCConsole::keyPressEvent
void keyPressEvent(QKeyEvent *) override
Definition: rpcconsole.cpp:914
RPCConsole::platformStyle
const PlatformStyle *const platformStyle
Definition: rpcconsole.h:162
ClientModel::node
interfaces::Node & node() const
Definition: clientmodel.h:55
RPCExecutor::m_node
interfaces::Node & m_node
Definition: rpcconsole.cpp:105
m_node
node::NodeContext m_node
Definition: bitcoin-gui.cpp:36
RPCConsole::updateNetworkState
void updateNetworkState()
Update UI with latest network info from model.
Definition: rpcconsole.cpp:956
ClientModel::peerTableSortProxy
PeerTableSortProxy * peerTableSortProxy()
Definition: clientmodel.cpp:193
RPCConsole::CMD_REQUEST
@ CMD_REQUEST
Definition: rpcconsole.h:58
PeerTableModel::Subversion
@ Subversion
Definition: peertablemodel.h:57
ClientModel::blocksDir
QString blocksDir() const
Definition: clientmodel.cpp:228
RPCTimerBase
Opaque base class for timers returned by NewTimerFunc.
Definition: server.h:50
GUIUtil::openDebugLogfile
void openDebugLogfile()
Definition: guiutil.cpp:420
peertablesortproxy.h
RPCConsole::showOrHideBanTableIfRequired
void showOrHideBanTableIfRequired()
Hides ban table if no bans are present.
Definition: rpcconsole.cpp:1333
PeerIdViewDelegate
Definition: rpcconsole.cpp:139
RPCConsole::autoCompleter
QCompleter * autoCompleter
Definition: rpcconsole.h:167
PeerIdViewDelegate::PeerIdViewDelegate
PeerIdViewDelegate(QObject *parent=nullptr)
Definition: rpcconsole.cpp:143
RPCConsole::CMD_ERROR
@ CMD_ERROR
Definition: rpcconsole.h:60
categoryClass
static QString categoryClass(int category)
Definition: rpcconsole.cpp:809
interfaces::Node::disconnectByAddress
virtual bool disconnectByAddress(const CNetAddr &net_addr)=0
Disconnect node by address.
RPCConsole::setTrafficGraphRange
void setTrafficGraphRange(int mins)
Definition: rpcconsole.cpp:1143
RPCConsole::RPCParseCommandLine
static bool RPCParseCommandLine(interfaces::Node *node, std::string &strResult, const std::string &strCommand, bool fExecute, std::string *const pstrFilteredOut=nullptr, const WalletModel *wallet_model=nullptr)
Split shell command line into a list of arguments and optionally execute the command(s).
Definition: rpcconsole.cpp:176
RPCConvertValues
UniValue RPCConvertValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Convert positional arguments to command-specific RPC representation.
Definition: client.cpp:246
bitcoin-config.h
bdb.h
chainparams.h
UniValue::write
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
Definition: univalue_write.cpp:28
RPCConsole::ui
Ui::RPCConsole *const ui
Definition: rpcconsole.h:156
ClientModel::getStatusBarWarnings
QString getStatusBarWarnings() const
Return warnings to be displayed in status bar.
Definition: clientmodel.cpp:178
RPCConsole::fontSmaller
void fontSmaller()
Definition: rpcconsole.cpp:825
PeerTableModel::Address
@ Address
Definition: peertablemodel.h:50
db.h
BanTableModel::Bantime
@ Bantime
Definition: bantablemodel.h:55
RPCConsole::m_is_executing
bool m_is_executing
Definition: rpcconsole.h:170
QtRPCTimerBase::timer
QTimer timer
Definition: rpcconsole.cpp:124
UniValue
Definition: univalue.h:17
QtRPCTimerInterface::NewTimer
RPCTimerBase * NewTimer(std::function< void()> &func, int64_t millis) override
Factory function for timers.
Definition: rpcconsole.cpp:133
RPCConsole::setMempoolSize
void setMempoolSize(long numberOfTxs, size_t dynUsage)
Set size (number of transactions and memory usage) of the mempool in the UI.
Definition: rpcconsole.cpp:990
rpcconsole.h
RPCConsole::tabShortcut
QKeySequence tabShortcut(TabTypes tab_type) const
Definition: rpcconsole.cpp:1353
RPCConsole::cachedNodeids
QList< NodeId > cachedNodeids
Definition: rpcconsole.h:161
RPCConsole::addWallet
void addWallet(WalletModel *const walletModel)
UniValue::get_str
const std::string & get_str() const
Definition: univalue_get.cpp:98
RPCConsole::updateTrafficStats
void updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut)
update traffic statistics
Definition: rpcconsole.cpp:1149
url
const char * url
Definition: rpcconsole.cpp:65
strencodings.h
UniValue::isStr
bool isStr() const
Definition: univalue.h:79
CONNECTION_TYPE_DOC
const std::vector< std::string > CONNECTION_TYPE_DOC
Definition: net.cpp:37
GUIUtil::ConnectionTypeToQString
QString ConnectionTypeToQString(ConnectionType conn_type, bool prepend_direction)
Convert enum ConnectionType to QString.
Definition: guiutil.cpp:685
GUIUtil::formatTimeOffset
QString formatTimeOffset(int64_t nTimeOffset)
Format a CNodeCombinedStats.nTimeOffset into a user-readable string.
Definition: guiutil.cpp:756
RPCConsole::consoleFontSize
int consoleFontSize
Definition: rpcconsole.h:166
GUIUtil::formatDurationStr
QString formatDurationStr(std::chrono::seconds dur)
Convert seconds into a QString with days, hours, mins, secs.
Definition: guiutil.cpp:714
LookupSubNet
bool LookupSubNet(const std::string &subnet_str, CSubNet &subnet_out)
Parse and resolve a specified subnet string into the appropriate internal representation.
Definition: netbase.cpp:679
RPCConsole::updateAlerts
void updateAlerts(const QString &warnings)
Definition: rpcconsole.cpp:1365
RPCConsole::setNetworkActive
void setNetworkActive(bool networkActive)
Set network state shown in the UI.
Definition: rpcconsole.cpp:977
RPCConsole::scrollToEnd
void scrollToEnd()
Scroll console view to end.
Definition: rpcconsole.cpp:1130
ClientModel::getPeerTableModel
PeerTableModel * getPeerTableModel()
Definition: clientmodel.cpp:188
RPCConsole::removeWallet
void removeWallet(WalletModel *const walletModel)
RPCConsole::showPeersTableContextMenu
void showPeersTableContextMenu(const QPoint &point)
Show custom context menu on Peers tab.
Definition: rpcconsole.cpp:1260
RPCConsole::setFontSize
void setFontSize(int newSize)
Definition: rpcconsole.cpp:830
PlatformStyle::SingleColorImage
QImage SingleColorImage(const QString &filename) const
Colorize an image (given filename) with the icon color.
Definition: platformstyle.cpp:98
RPCConsole::RPCConsole
RPCConsole(interfaces::Node &node, const PlatformStyle *platformStyle, QWidget *parent)
Definition: rpcconsole.cpp:474
RPCConsole::cmdRequest
void cmdRequest(const QString &command, const WalletModel *wallet_model)
PACKAGE_NAME
#define PACKAGE_NAME
Definition: bitcoin-config.h:354
RPCConsole::m_last_wallet_model
WalletModel * m_last_wallet_model
Definition: rpcconsole.h:169
PlatformStyle::getImagesOnButtons
bool getImagesOnButtons() const
Definition: platformstyle.h:21
RPCConsole::setClientModel
void setClientModel(ClientModel *model=nullptr, int bestblock_height=0, int64_t bestblock_date=0, double verification_progress=0.0)
Definition: rpcconsole.cpp:652
node.h
ClientModel::bytesChanged
void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut)
RPCConsole::CMD_REPLY
@ CMD_REPLY
Definition: rpcconsole.h:59
util::ThreadRename
void ThreadRename(std::string &&)
Rename a thread both in terms of an internal (in-memory) name as well as its system thread name.
Definition: threadnames.cpp:57
RPCConsole::showEvent
void showEvent(QShowEvent *event) override
Definition: rpcconsole.cpp:1233
RPCConsole::on_tabWidget_currentChanged
void on_tabWidget_currentChanged(int index)
Definition: rpcconsole.cpp:1118
univalue.h
QtRPCTimerInterface::Name
const char * Name() override
Implementation name.
Definition: rpcconsole.cpp:132
RPCConsole::disconnectSelectedNode
void disconnectSelectedNode()
Disconnect a selected node on the Peers tab.
Definition: rpcconsole.cpp:1274
interfaces::Node::listRpcCommands
virtual std::vector< std::string > listRpcCommands()=0
List rpc commands.
RPCConsole
Local Bitcoin RPC console.
Definition: rpcconsole.h:38
CONSOLE_HISTORY
const int CONSOLE_HISTORY
Definition: rpcconsole.cpp:59
RPCConsole::TranslatedStrings::to
const QString to
Definition: rpcconsole.h:138
RPCConsole::BANSUBNET_COLUMN_WIDTH
@ BANSUBNET_COLUMN_WIDTH
Definition: rpcconsole.h:150
GUIUtil::AddButtonShortcut
void AddButtonShortcut(QAbstractButton *button, const QKeySequence &shortcut)
Connects an additional shortcut to a QAbstractButton.
Definition: guiutil.cpp:133
CSubNet
Definition: netaddress.h:475
guiutil.h
ClientModel::formatFullVersion
QString formatFullVersion() const
Definition: clientmodel.cpp:203
WalletModel::getWalletName
QString getWalletName() const
Definition: walletmodel.cpp:577
RPCConsole::clear
void clear(bool keep_prompt=false)
Definition: rpcconsole.cpp:855
RPCConsole::PING_COLUMN_WIDTH
@ PING_COLUMN_WIDTH
Definition: rpcconsole.h:149
RPCConsole::showBanTableContextMenu
void showBanTableContextMenu(const QPoint &point)
Show custom context menu on Bans tab.
Definition: rpcconsole.cpp:1267
RPCConsole::SUBVERSION_COLUMN_WIDTH
@ SUBVERSION_COLUMN_WIDTH
Definition: rpcconsole.h:148
CNodeCombinedStats
Definition: peertablemodel.h:27
QtRPCTimerInterface
Definition: rpcconsole.cpp:128
GUIUtil::formatBytes
QString formatBytes(uint64_t bytes)
Definition: guiutil.cpp:798
RPCConsole::BANTIME_COLUMN_WIDTH
@ BANTIME_COLUMN_WIDTH
Definition: rpcconsole.h:151
GUIUtil::formatServicesStr
QString formatServicesStr(quint64 mask)
Format CNodeStats.nServices bitmask into a user-readable string.
Definition: guiutil.cpp:735
RPCConsole::hideEvent
void hideEvent(QHideEvent *event) override
Definition: rpcconsole.cpp:1244
RPCConsole::updateDetailWidget
void updateDetailWidget()
show detailed information on ui about selected node
Definition: rpcconsole.cpp:1155
RPCConsole::m_banlist_widget_header_state
QByteArray m_banlist_widget_header_state
Definition: rpcconsole.h:172
UniValue::isArray
bool isArray() const
Definition: univalue.h:81
GUIUtil::fixedPitchFont
QFont fixedPitchFont(bool use_embedded_font)
Definition: guiutil.cpp:94
RPCConsole::m_node
interfaces::Node & m_node
Definition: rpcconsole.h:155
interfaces::Node::unban
virtual bool unban(const CSubNet &ip)=0
Unban node.
RPCConsole::thread
QThread thread
Definition: rpcconsole.h:168
RPCConsole::TabTypes::GRAPH
@ GRAPH
interfaces::Node
Top-level interface for a bitcoin node (bitcoind process).
Definition: node.h:68
RPCConsole::tabTitle
QString tabTitle(TabTypes tab_type) const
Definition: rpcconsole.cpp:1348
RPCConsole::TimeDurationField
QString TimeDurationField(std::chrono::seconds time_now, std::chrono::seconds time_at_event) const
Helper for the output of a time duration field.
Definition: rpcconsole.h:178
RPCConsole::TranslatedStrings::na
const QString na
Definition: rpcconsole.h:139
RPCConsole::~RPCConsole
~RPCConsole()
Definition: rpcconsole.cpp:584
BanTableModel::shouldShow
bool shouldShow()
Definition: bantablemodel.cpp:180
PeerTableModel::Ping
@ Ping
Definition: peertablemodel.h:54
platformstyle.h
RPCConsole::history
QStringList history
Definition: rpcconsole.h:158
system.h
PeerTableModel::StatsRole
@ StatsRole
Definition: peertablemodel.h:61
RPCConsole::TranslatedStrings::unknown
const QString unknown
Definition: rpcconsole.h:139
RPCConsole::TabTypes
TabTypes
Definition: rpcconsole.h:63
TrafficGraphWidget::clear
void clear()
Definition: trafficgraphwidget.cpp:163
RPCConsole::cmdBeforeBrowsing
QString cmdBeforeBrowsing
Definition: rpcconsole.h:160
RPCExecutor
Definition: rpcconsole.cpp:92
ClientModel
Model for Bitcoin network client.
Definition: clientmodel.h:47
Join
auto Join(const std::vector< T > &list, const BaseType &separator, UnaryOp unary_op) -> decltype(unary_op(list.at(0)))
Join a list of items.
Definition: string.h:44
RPCConsole::eventFilter
virtual bool eventFilter(QObject *obj, QEvent *event) override
Definition: rpcconsole.cpp:607
Ui
Definition: addressbookpage.h:14
GUIUtil::HtmlEscape
QString HtmlEscape(const QString &str, bool fMultiLine)
Definition: guiutil.cpp:239
RPCConsole::setTabFocus
void setTabFocus(enum TabTypes tabType)
set which tab has the focus (is visible)
Definition: rpcconsole.cpp:1343
UniValue::get_int
int get_int() const
Definition: univalue_get.cpp:105
GUIUtil::copyEntryData
void copyEntryData(const QAbstractItemView *view, int column, int role)
Copy a field of the currently selected entry of a view to the clipboard.
Definition: guiutil.cpp:254
RPCConsole::on_lineEdit_returnPressed
void on_lineEdit_returnPressed()
Definition: rpcconsole.cpp:1000
ClientModel::formatSubVersion
QString formatSubVersion() const
Definition: clientmodel.cpp:208
RPCConsole::peersTableContextMenu
QMenu * peersTableContextMenu
Definition: rpcconsole.h:164
QtRPCTimerInterface::~QtRPCTimerInterface
~QtRPCTimerInterface()
Definition: rpcconsole.cpp:131
GUIUtil::IsEscapeOrBack
bool IsEscapeOrBack(int key)
Definition: guiutil.h:431
ClientModel::formatClientStartupTime
QString formatClientStartupTime() const
Definition: clientmodel.cpp:218
QtRPCTimerBase::QtRPCTimerBase
QtRPCTimerBase(std::function< void()> &_func, int64_t millis)
Definition: rpcconsole.cpp:115
PeerTableModel::startAutoRefresh
void startAutoRefresh()
Definition: peertablemodel.cpp:36
RPCConsole::RPCExecuteCommandLine
static bool RPCExecuteCommandLine(interfaces::Node &node, std::string &strResult, const std::string &strCommand, std::string *const pstrFilteredOut=nullptr, const WalletModel *wallet_model=nullptr)
Definition: rpcconsole.h:47
interfaces::Node::rpcSetTimerInterfaceIfUnset
virtual void rpcSetTimerInterfaceIfUnset(RPCTimerInterface *iface)=0
Set RPC timer interface if unset.
RPCConsole::message
void message(int category, const QString &msg)
Append the message to the message widget.
Definition: rpcconsole.h:109
UniValue::push_back
bool push_back(const UniValue &val)
Definition: univalue.cpp:108
GUIUtil::NetworkToQString
QString NetworkToQString(Network net)
Convert enum Network to QString.
Definition: guiutil.cpp:670
Params
const CChainParams & Params()
Return the currently selected parameters.
Definition: chainparams.cpp:561
CSubNet::IsValid
bool IsValid() const
Definition: netaddress.cpp:1219
ClientModel::dataDir
QString dataDir() const
Definition: clientmodel.cpp:223
node
Definition: init.h:22
RPCConsole::on_openDebugLogfileButton_clicked
void on_openDebugLogfileButton_clicked()
open the debug.log from the current datadir
Definition: rpcconsole.cpp:1125
FONT_RANGE
const QSize FONT_RANGE(4, 40)
ICON_MAPPING
const struct @8 ICON_MAPPING[]
RPCConsole::browseHistory
void browseHistory(int offset)
Go forward or back in history.
Definition: rpcconsole.cpp:1069
RPCExecutor::reply
void reply(int category, const QString &command)
RPCConsole::historyPtr
int historyPtr
Definition: rpcconsole.h:159
RPCConsole::on_sldGraphRange_valueChanged
void on_sldGraphRange_valueChanged(int value)
change the time range of the network traffic graph
Definition: rpcconsole.cpp:1136
bantablemodel.h
RPCExecutor::request
void request(const QString &command, const WalletModel *wallet_model)
Definition: rpcconsole.cpp:418
interfaces::Node::rpcUnsetTimerInterface
virtual void rpcUnsetTimerInterface(RPCTimerInterface *iface)=0
Unset RPC timer interface.
netbase.h
RPCConsole::setNumBlocks
void setNumBlocks(int count, const QDateTime &blockDate, double nVerificationProgress, bool headers)
Set number of blocks and last block date shown in the UI.
Definition: rpcconsole.cpp:982
GUIUtil::handleCloseWindowShortcut
void handleCloseWindowShortcut(QWidget *w)
Definition: guiutil.cpp:415
find_value
const UniValue & find_value(const UniValue &obj, const std::string &name)
Definition: univalue.cpp:236
RPCConsole::fontBigger
void fontBigger()
Definition: rpcconsole.cpp:820
RPCConsole::TranslatedStrings::no
const QString no
Definition: rpcconsole.h:138
GUIUtil::getEntryData
QList< QModelIndex > getEntryData(const QAbstractItemView *view, int column)
Return a field of the currently selected entry as a QString.
Definition: guiutil.cpp:267
RPCConsole::changeEvent
void changeEvent(QEvent *e) override
Definition: rpcconsole.cpp:921
WalletModel::getDisplayName
QString getDisplayName() const
Definition: walletmodel.cpp:582
server.h
PlatformStyle
Definition: platformstyle.h:13
GUIUtil::formatPingTime
QString formatPingTime(std::chrono::microseconds ping_time)
Format a CNodeStats.m_last_ping_time into a user-readable string or display N/A, if 0.
Definition: guiutil.cpp:749
RPCConsole::unbanSelectedNode
void unbanSelectedNode()
Unban a selected node on the Bans tab.
Definition: rpcconsole.cpp:1305
PeerTableModel::stopAutoRefresh
void stopAutoRefresh()
Definition: peertablemodel.cpp:41
threadnames.h
RPCConsole::ts
struct RPCConsole::TranslatedStrings ts
QtRPCTimerBase::~QtRPCTimerBase
~QtRPCTimerBase()
Definition: rpcconsole.cpp:122
RPCConsole::rpcTimerInterface
RPCTimerInterface * rpcTimerInterface
Definition: rpcconsole.h:163
RPCConsole::banSelectedNode
void banSelectedNode(int bantime)
Ban a selected node on the Peers tab.
Definition: rpcconsole.cpp:1288
BanTableModel::refresh
void refresh()
Definition: bantablemodel.cpp:166
QtRPCTimerBase::func
std::function< void()> func
Definition: rpcconsole.cpp:125
client.h
RPCConsole::clientModel
ClientModel * clientModel
Definition: rpcconsole.h:157
ClientModel::networkActiveChanged
void networkActiveChanged(bool networkActive)
RPCConsole::banTableContextMenu
QMenu * banTableContextMenu
Definition: rpcconsole.h:165
clientmodel.h
RPCConsole::TabTypes::INFO
@ INFO
BanTableModel::Address
@ Address
Definition: bantablemodel.h:54
UniValue::isObject
bool isObject() const
Definition: univalue.h:82
ClientModel::getBanTableModel
BanTableModel * getBanTableModel()
Definition: clientmodel.cpp:198
RPCConsole::TabTypes::PEERS
@ PEERS