Fabcoin Core  0.16.2
P2P Digital Currency
rpcconsole.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2017 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 <rpcconsole.h>
10 #include <ui_debugwindow.h>
11 
12 #include <bantablemodel.h>
13 #include <clientmodel.h>
14 #include <guiutil.h>
15 #include <platformstyle.h>
16 #include <chainparams.h>
17 #include <netbase.h>
18 #include <rpc/server.h>
19 #include <rpc/client.h>
20 #include <util.h>
21 #include <styleSheet.h>
22 
23 #include <openssl/crypto.h>
24 
25 #include <univalue.h>
26 
27 #ifdef ENABLE_WALLET
28 #include <db_cxx.h>
29 #include <wallet/wallet.h>
30 #endif
31 
32 #include <QDesktopWidget>
33 #include <QKeyEvent>
34 #include <QMenu>
35 #include <QMessageBox>
36 #include <QScrollBar>
37 #include <QSettings>
38 #include <QSignalMapper>
39 #include <QThread>
40 #include <QTime>
41 #include <QTimer>
42 #include <QStringList>
43 #include <QStyledItemDelegate>
44 
45 #if QT_VERSION < 0x050000
46 #include <QUrl>
47 #endif
48 
49 // TODO: add a scrollback limit, as there is currently none
50 // TODO: make it possible to filter out categories (esp debug messages when implemented)
51 // TODO: receive errors and debug messages through ClientModel
52 
53 const int CONSOLE_HISTORY = 50;
55 const QSize FONT_RANGE(4, 40);
56 const char fontSizeSettingsKey[] = "consoleFontSize";
57 
58 const struct {
59  const char *url;
60  const char *source;
62 } ICON_MAPPING[] = {
63  {"cmd-request", ":/icons/tx_input", PlatformStyle::Input},
64  {"cmd-reply", ":/icons/tx_output", PlatformStyle::Output},
65  {"cmd-error", ":/icons/tx_output", PlatformStyle::Error},
66  {"misc", ":/icons/tx_inout", PlatformStyle::Inout},
67  {NULL, NULL, PlatformStyle::Inout}
68 };
69 
70 namespace {
71 
72 // don't add private key handling cmd's to the history
73 const QStringList historyFilter = QStringList()
74  << "importprivkey"
75  << "importmulti"
76  << "signmessagewithprivkey"
77  << "signrawtransaction"
78  << "walletpassphrase"
79  << "walletpassphrasechange"
80  << "encryptwallet";
81 
82 }
83 
84 /* Object for executing console RPC commands in a separate thread.
85 */
86 class RPCExecutor : public QObject
87 {
88  Q_OBJECT
89 
90 public Q_SLOTS:
91  void request(const QString &command);
92 
93 Q_SIGNALS:
94  void reply(int category, const QString &command);
95 };
96 
100 class QtRPCTimerBase: public QObject, public RPCTimerBase
101 {
102  Q_OBJECT
103 public:
104  QtRPCTimerBase(std::function<void(void)>& _func, int64_t millis):
105  func(_func)
106  {
107  timer.setSingleShot(true);
108  connect(&timer, SIGNAL(timeout()), this, SLOT(timeout()));
109  timer.start(millis);
110  }
112 private Q_SLOTS:
113  void timeout() { func(); }
114 private:
115  QTimer timer;
116  std::function<void(void)> func;
117 };
118 
120 {
121 public:
123  const char *Name() { return "Qt"; }
124  RPCTimerBase* NewTimer(std::function<void(void)>& func, int64_t millis)
125  {
126  return new QtRPCTimerBase(func, millis);
127  }
128 };
129 
130 
131 #include <rpcconsole.moc>
132 
152 bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &strCommand, const bool fExecute, std::string * const pstrFilteredOut)
153 {
154  std::vector< std::vector<std::string> > stack;
155  stack.push_back(std::vector<std::string>());
156 
157  enum CmdParseState
158  {
159  STATE_EATING_SPACES,
160  STATE_EATING_SPACES_IN_ARG,
161  STATE_EATING_SPACES_IN_BRACKETS,
162  STATE_ARGUMENT,
163  STATE_SINGLEQUOTED,
164  STATE_DOUBLEQUOTED,
165  STATE_ESCAPE_OUTER,
166  STATE_ESCAPE_DOUBLEQUOTED,
167  STATE_COMMAND_EXECUTED,
168  STATE_COMMAND_EXECUTED_INNER
169  } state = STATE_EATING_SPACES;
170  std::string curarg;
171  UniValue lastResult;
172  unsigned nDepthInsideSensitive = 0;
173  size_t filter_begin_pos = 0, chpos;
174  std::vector<std::pair<size_t, size_t>> filter_ranges;
175 
176  auto add_to_current_stack = [&](const std::string& strArg) {
177  if (stack.back().empty() && (!nDepthInsideSensitive) && historyFilter.contains(QString::fromStdString(strArg), Qt::CaseInsensitive)) {
178  nDepthInsideSensitive = 1;
179  filter_begin_pos = chpos;
180  }
181  // Make sure stack is not empty before adding something
182  if (stack.empty()) {
183  stack.push_back(std::vector<std::string>());
184  }
185  stack.back().push_back(strArg);
186  };
187 
188  auto close_out_params = [&]() {
189  if (nDepthInsideSensitive) {
190  if (!--nDepthInsideSensitive) {
191  assert(filter_begin_pos);
192  filter_ranges.push_back(std::make_pair(filter_begin_pos, chpos));
193  filter_begin_pos = 0;
194  }
195  }
196  stack.pop_back();
197  };
198 
199  std::string strCommandTerminated = strCommand;
200  if (strCommandTerminated.back() != '\n')
201  strCommandTerminated += "\n";
202  for (chpos = 0; chpos < strCommandTerminated.size(); ++chpos)
203  {
204  char ch = strCommandTerminated[chpos];
205  switch(state)
206  {
207  case STATE_COMMAND_EXECUTED_INNER:
208  case STATE_COMMAND_EXECUTED:
209  {
210  bool breakParsing = true;
211  switch(ch)
212  {
213  case '[': curarg.clear(); state = STATE_COMMAND_EXECUTED_INNER; break;
214  default:
215  if (state == STATE_COMMAND_EXECUTED_INNER)
216  {
217  if (ch != ']')
218  {
219  // append char to the current argument (which is also used for the query command)
220  curarg += ch;
221  break;
222  }
223  if (curarg.size() && fExecute)
224  {
225  // if we have a value query, query arrays with index and objects with a string key
226  UniValue subelement;
227  if (lastResult.isArray())
228  {
229  for(char argch: curarg)
230  if (!std::isdigit(argch))
231  throw std::runtime_error("Invalid result query");
232  subelement = lastResult[atoi(curarg.c_str())];
233  }
234  else if (lastResult.isObject())
235  subelement = find_value(lastResult, curarg);
236  else
237  throw std::runtime_error("Invalid result query"); //no array or object: abort
238  lastResult = subelement;
239  }
240 
241  state = STATE_COMMAND_EXECUTED;
242  break;
243  }
244  // don't break parsing when the char is required for the next argument
245  breakParsing = false;
246 
247  // pop the stack and return the result to the current command arguments
248  close_out_params();
249 
250  // don't stringify the json in case of a string to avoid doublequotes
251  if (lastResult.isStr())
252  curarg = lastResult.get_str();
253  else
254  curarg = lastResult.write(2);
255 
256  // if we have a non empty result, use it as stack argument otherwise as general result
257  if (curarg.size())
258  {
259  if (stack.size())
260  add_to_current_stack(curarg);
261  else
262  strResult = curarg;
263  }
264  curarg.clear();
265  // assume eating space state
266  state = STATE_EATING_SPACES;
267  }
268  if (breakParsing)
269  break;
270  }
271  case STATE_ARGUMENT: // In or after argument
272  case STATE_EATING_SPACES_IN_ARG:
273  case STATE_EATING_SPACES_IN_BRACKETS:
274  case STATE_EATING_SPACES: // Handle runs of whitespace
275  switch(ch)
276  {
277  case '"': state = STATE_DOUBLEQUOTED; break;
278  case '\'': state = STATE_SINGLEQUOTED; break;
279  case '\\': state = STATE_ESCAPE_OUTER; break;
280  case '(': case ')': case '\n':
281  if (state == STATE_EATING_SPACES_IN_ARG)
282  throw std::runtime_error("Invalid Syntax");
283  if (state == STATE_ARGUMENT)
284  {
285  if (ch == '(' && stack.size() && stack.back().size() > 0)
286  {
287  if (nDepthInsideSensitive) {
288  ++nDepthInsideSensitive;
289  }
290  stack.push_back(std::vector<std::string>());
291  }
292 
293  // don't allow commands after executed commands on baselevel
294  if (!stack.size())
295  throw std::runtime_error("Invalid Syntax");
296 
297  add_to_current_stack(curarg);
298  curarg.clear();
299  state = STATE_EATING_SPACES_IN_BRACKETS;
300  }
301  if ((ch == ')' || ch == '\n') && stack.size() > 0)
302  {
303  if (fExecute) {
304  // Convert argument list to JSON objects in method-dependent way,
305  // and pass it along with the method name to the dispatcher.
306  JSONRPCRequest req;
307  req.params = RPCConvertValues(stack.back()[0], std::vector<std::string>(stack.back().begin() + 1, stack.back().end()));
308  req.strMethod = stack.back()[0];
309 #ifdef ENABLE_WALLET
310  // TODO: Move this logic to WalletModel
311  if (!vpwallets.empty()) {
312  // in Qt, use always the wallet with index 0 when running with multiple wallets
313  QByteArray encodedName = QUrl::toPercentEncoding(QString::fromStdString(vpwallets[0]->GetName()));
314  req.URI = "/wallet/"+std::string(encodedName.constData(), encodedName.length());
315  }
316 #endif
317  lastResult = tableRPC.execute(req);
318  }
319 
320  state = STATE_COMMAND_EXECUTED;
321  curarg.clear();
322  }
323  break;
324  case ' ': case ',': case '\t':
325  if(state == STATE_EATING_SPACES_IN_ARG && curarg.empty() && ch == ',')
326  throw std::runtime_error("Invalid Syntax");
327 
328  else if(state == STATE_ARGUMENT) // Space ends argument
329  {
330  add_to_current_stack(curarg);
331  curarg.clear();
332  }
333  if ((state == STATE_EATING_SPACES_IN_BRACKETS || state == STATE_ARGUMENT) && ch == ',')
334  {
335  state = STATE_EATING_SPACES_IN_ARG;
336  break;
337  }
338  state = STATE_EATING_SPACES;
339  break;
340  default: curarg += ch; state = STATE_ARGUMENT;
341  }
342  break;
343  case STATE_SINGLEQUOTED: // Single-quoted string
344  switch(ch)
345  {
346  case '\'': state = STATE_ARGUMENT; break;
347  default: curarg += ch;
348  }
349  break;
350  case STATE_DOUBLEQUOTED: // Double-quoted string
351  switch(ch)
352  {
353  case '"': state = STATE_ARGUMENT; break;
354  case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break;
355  default: curarg += ch;
356  }
357  break;
358  case STATE_ESCAPE_OUTER: // '\' outside quotes
359  curarg += ch; state = STATE_ARGUMENT;
360  break;
361  case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text
362  if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself
363  curarg += ch; state = STATE_DOUBLEQUOTED;
364  break;
365  }
366  }
367  if (pstrFilteredOut) {
368  if (STATE_COMMAND_EXECUTED == state) {
369  assert(!stack.empty());
370  close_out_params();
371  }
372  *pstrFilteredOut = strCommand;
373  for (auto i = filter_ranges.rbegin(); i != filter_ranges.rend(); ++i) {
374  pstrFilteredOut->replace(i->first, i->second - i->first, "(…)");
375  }
376  }
377  switch(state) // final state
378  {
379  case STATE_COMMAND_EXECUTED:
380  if (lastResult.isStr())
381  strResult = lastResult.get_str();
382  else
383  strResult = lastResult.write(2);
384  case STATE_ARGUMENT:
385  case STATE_EATING_SPACES:
386  return true;
387  default: // ERROR to end in one of the other states
388  return false;
389  }
390 }
391 
392 void RPCExecutor::request(const QString &command)
393 {
394  try
395  {
396  std::string result;
397  std::string executableCommand = command.toStdString() + "\n";
398  if(!RPCConsole::RPCExecuteCommandLine(result, executableCommand))
399  {
400  Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \""));
401  return;
402  }
403  Q_EMIT reply(RPCConsole::CMD_REPLY, QString::fromStdString(result));
404  }
405  catch (UniValue& objError)
406  {
407  try // Nice formatting for standard-format error
408  {
409  int code = find_value(objError, "code").get_int();
410  std::string message = find_value(objError, "message").get_str();
411  Q_EMIT reply(RPCConsole::CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")");
412  }
413  catch (const std::runtime_error&) // raised when converting to invalid type, i.e. missing code or message
414  { // Show raw JSON object
415  Q_EMIT reply(RPCConsole::CMD_ERROR, QString::fromStdString(objError.write()));
416  }
417  }
418  catch (const std::exception& e)
419  {
420  Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what()));
421  }
422 }
423 
424 RPCConsole::RPCConsole(const PlatformStyle *_platformStyle, QWidget *parent) :
425  QWidget(parent),
426  ui(new Ui::RPCConsole),
427  clientModel(0),
428  historyPtr(0),
429  platformStyle(_platformStyle),
430  peersTableContextMenu(0),
431  banTableContextMenu(0),
432  consoleFontSize(0)
433 {
434  ui->setupUi(this);
435  QSettings settings;
436  if (!restoreGeometry(settings.value("RPCConsoleWindowGeometry").toByteArray())) {
437  // Restore failed (perhaps missing setting), center the window
438  move(QApplication::desktop()->availableGeometry().center() - frameGeometry().center());
439  }
440 
441  // Set stylesheet
442  SetObjectStyleSheet(ui->promptIcon, StyleSheetNames::ButtonTransparent);
443  SetObjectStyleSheet(ui->clearButton, StyleSheetNames::ButtonTransparent);
444  SetObjectStyleSheet(ui->fontBiggerButton, StyleSheetNames::ButtonTransparent);
445  SetObjectStyleSheet(ui->fontSmallerButton, StyleSheetNames::ButtonTransparent);
446  SetObjectStyleSheet(ui->openDebugLogfileButton, StyleSheetNames::ButtonBlue);
447  SetObjectStyleSheet(ui->btnClearTrafficGraph, StyleSheetNames::ButtonBlue);
448  SetObjectStyleSheet(ui->peerWidget, StyleSheetNames::TableViewLight);
449  SetObjectStyleSheet(ui->banlistWidget, StyleSheetNames::TableViewLight);
450 
451  ui->openDebugLogfileButton->setToolTip(ui->openDebugLogfileButton->toolTip().arg(tr(PACKAGE_NAME)));
452 
455  }
458  ui->fontSmallerButton->setIcon(platformStyle->MultiStatesIcon(":/icons/fontsmaller", PlatformStyle::PushButton));
459  ui->promptIcon->setIcon(platformStyle->MultiStatesIcon(":/icons/prompticon", PlatformStyle::PushButton));
460 
461  // Install event filter for up and down arrow
462  ui->lineEdit->installEventFilter(this);
463  ui->messagesWidget->installEventFilter(this);
464 
465  connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
466  connect(ui->fontBiggerButton, SIGNAL(clicked()), this, SLOT(fontBigger()));
467  connect(ui->fontSmallerButton, SIGNAL(clicked()), this, SLOT(fontSmaller()));
468  connect(ui->btnClearTrafficGraph, SIGNAL(clicked()), ui->trafficGraph, SLOT(clear()));
469 
470  // set library version labels
471 #ifdef ENABLE_WALLET
472  ui->berkeleyDBVersion->setText(DbEnv::version(0, 0, 0));
473 #else
474  ui->label_berkeleyDBVersion->hide();
475  ui->berkeleyDBVersion->hide();
476 #endif
477  // Register RPC timer interface
479  // avoid accidentally overwriting an existing, non QTThread
480  // based timer interface
482 
484 
485  ui->detailWidget->hide();
486  ui->peerHeading->setText(tr("Select a peer to view detailed information."));
487 
488  consoleFontSize = settings.value(fontSizeSettingsKey, QFontInfo(QFont()).pointSize()).toInt();
489  clear();
490 }
491 
493 {
494  QSettings settings;
495  settings.setValue("RPCConsoleWindowGeometry", saveGeometry());
497  delete rpcTimerInterface;
498  delete ui;
499 }
500 
501 bool RPCConsole::eventFilter(QObject* obj, QEvent *event)
502 {
503  if(event->type() == QEvent::KeyPress) // Special key handling
504  {
505  QKeyEvent *keyevt = static_cast<QKeyEvent*>(event);
506  int key = keyevt->key();
507  Qt::KeyboardModifiers mod = keyevt->modifiers();
508  switch(key)
509  {
510  case Qt::Key_Up: if(obj == ui->lineEdit) { browseHistory(-1); return true; } break;
511  case Qt::Key_Down: if(obj == ui->lineEdit) { browseHistory(1); return true; } break;
512  case Qt::Key_PageUp: /* pass paging keys to messages widget */
513  case Qt::Key_PageDown:
514  if(obj == ui->lineEdit)
515  {
516  QApplication::postEvent(ui->messagesWidget, new QKeyEvent(*keyevt));
517  return true;
518  }
519  break;
520  case Qt::Key_Return:
521  case Qt::Key_Enter:
522  // forward these events to lineEdit
523  if(obj == autoCompleter->popup()) {
524  QApplication::postEvent(ui->lineEdit, new QKeyEvent(*keyevt));
525  return true;
526  }
527  break;
528  default:
529  // Typing in messages widget brings focus to line edit, and redirects key there
530  // Exclude most combinations and keys that emit no text, except paste shortcuts
531  if(obj == ui->messagesWidget && (
532  (!mod && !keyevt->text().isEmpty() && key != Qt::Key_Tab) ||
533  ((mod & Qt::ControlModifier) && key == Qt::Key_V) ||
534  ((mod & Qt::ShiftModifier) && key == Qt::Key_Insert)))
535  {
536  ui->lineEdit->setFocus();
537  QApplication::postEvent(ui->lineEdit, new QKeyEvent(*keyevt));
538  return true;
539  }
540  }
541  }
542  return QWidget::eventFilter(obj, event);
543 }
544 
546 {
547  clientModel = model;
548  ui->trafficGraph->setClientModel(model);
550  // Keep up to date with client
552  connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
553 
554  setNumBlocks(model->getNumBlocks(), model->getLastBlockDate(), model->getVerificationProgress(nullptr), false);
555  connect(model, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(setNumBlocks(int,QDateTime,double,bool)));
556 
558  connect(model, SIGNAL(networkActiveChanged(bool)), this, SLOT(setNetworkActive(bool)));
559 
561  connect(model, SIGNAL(bytesChanged(quint64,quint64)), this, SLOT(updateTrafficStats(quint64, quint64)));
562 
563  connect(model, SIGNAL(mempoolSizeChanged(long,size_t)), this, SLOT(setMempoolSize(long,size_t)));
564 
565  // set up peer table
566  ui->peerWidget->setModel(model->getPeerTableModel());
567  ui->peerWidget->verticalHeader()->hide();
568  ui->peerWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
569  ui->peerWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
570  ui->peerWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
571  ui->peerWidget->setContextMenuPolicy(Qt::CustomContextMenu);
575  ui->peerWidget->horizontalHeader()->setStretchLastSection(true);
576 
577  // create peer table context menu actions
578  QAction* disconnectAction = new QAction(tr("&Disconnect"), this);
579  QAction* banAction1h = new QAction(tr("Ban for") + " " + tr("1 &hour"), this);
580  QAction* banAction24h = new QAction(tr("Ban for") + " " + tr("1 &day"), this);
581  QAction* banAction7d = new QAction(tr("Ban for") + " " + tr("1 &week"), this);
582  QAction* banAction365d = new QAction(tr("Ban for") + " " + tr("1 &year"), this);
583 
584  // create peer table context menu
585  peersTableContextMenu = new QMenu(this);
586  peersTableContextMenu->addAction(disconnectAction);
587  peersTableContextMenu->addAction(banAction1h);
588  peersTableContextMenu->addAction(banAction24h);
589  peersTableContextMenu->addAction(banAction7d);
590  peersTableContextMenu->addAction(banAction365d);
591 
592  // Add a signal mapping to allow dynamic context menu arguments.
593  // We need to use int (instead of int64_t), because signal mapper only supports
594  // int or objects, which is okay because max bantime (1 year) is < int_max.
595  QSignalMapper* signalMapper = new QSignalMapper(this);
596  signalMapper->setMapping(banAction1h, 60*60);
597  signalMapper->setMapping(banAction24h, 60*60*24);
598  signalMapper->setMapping(banAction7d, 60*60*24*7);
599  signalMapper->setMapping(banAction365d, 60*60*24*365);
600  connect(banAction1h, SIGNAL(triggered()), signalMapper, SLOT(map()));
601  connect(banAction24h, SIGNAL(triggered()), signalMapper, SLOT(map()));
602  connect(banAction7d, SIGNAL(triggered()), signalMapper, SLOT(map()));
603  connect(banAction365d, SIGNAL(triggered()), signalMapper, SLOT(map()));
604  connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(banSelectedNode(int)));
605 
606  // peer table context menu signals
607  connect(ui->peerWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showPeersTableContextMenu(const QPoint&)));
608  connect(disconnectAction, SIGNAL(triggered()), this, SLOT(disconnectSelectedNode()));
609 
610  // peer table signal handling - update peer details when selecting new node
611  connect(ui->peerWidget->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
612  this, SLOT(peerSelected(const QItemSelection &, const QItemSelection &)));
613  // peer table signal handling - update peer details when new nodes are added to the model
614  connect(model->getPeerTableModel(), SIGNAL(layoutChanged()), this, SLOT(peerLayoutChanged()));
615  // peer table signal handling - cache selected node ids
616  connect(model->getPeerTableModel(), SIGNAL(layoutAboutToBeChanged()), this, SLOT(peerLayoutAboutToChange()));
617 
618  // set up ban table
619  ui->banlistWidget->setModel(model->getBanTableModel());
620  ui->banlistWidget->verticalHeader()->hide();
621  ui->banlistWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
622  ui->banlistWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
623  ui->banlistWidget->setSelectionMode(QAbstractItemView::SingleSelection);
624  ui->banlistWidget->setContextMenuPolicy(Qt::CustomContextMenu);
627  ui->banlistWidget->horizontalHeader()->setStretchLastSection(true);
628 
629  // create ban table context menu action
630  QAction* unbanAction = new QAction(tr("&Unban"), this);
631 
632  // create ban table context menu
633  banTableContextMenu = new QMenu(this);
634  banTableContextMenu->addAction(unbanAction);
635 
636  // ban table context menu signals
637  connect(ui->banlistWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showBanTableContextMenu(const QPoint&)));
638  connect(unbanAction, SIGNAL(triggered()), this, SLOT(unbanSelectedNode()));
639 
640  // ban table signal handling - clear peer details when clicking a peer in the ban table
641  connect(ui->banlistWidget, SIGNAL(clicked(const QModelIndex&)), this, SLOT(clearSelectedNode()));
642  // ban table signal handling - ensure ban table is shown or hidden (if empty)
643  connect(model->getBanTableModel(), SIGNAL(layoutChanged()), this, SLOT(showOrHideBanTableIfRequired()));
645 
646  // Provide initial values
647  ui->clientVersion->setText(model->formatFullVersion());
648  ui->clientUserAgent->setText(model->formatSubVersion());
649  ui->dataDir->setText(model->dataDir());
650  ui->startupTime->setText(model->formatClientStartupTime());
651  ui->networkName->setText(QString::fromStdString(Params().NetworkIDString()));
652 
653  //Setup autocomplete and attach it
654  QStringList wordList;
655  std::vector<std::string> commandList = tableRPC.listCommands();
656  for (size_t i = 0; i < commandList.size(); ++i)
657  {
658  wordList << commandList[i].c_str();
659  wordList << ("help " + commandList[i]).c_str();
660  }
661 
662  wordList.sort();
663  autoCompleter = new QCompleter(wordList, this);
664  autoCompleter->setModelSorting(QCompleter::CaseSensitivelySortedModel);
665  ui->lineEdit->setCompleter(autoCompleter);
666  autoCompleter->popup()->installEventFilter(this);
667  autoCompleter->popup()->setItemDelegate(new QStyledItemDelegate(this));
668  autoCompleter->popup()->setObjectName("autoCompleterPopup");
669 
670  // Start thread to execute RPC commands.
671  startExecutor();
672  }
673  if (!model) {
674  // Client model is being set to 0, this means shutdown() is about to be called.
675  // Make sure we clean up the executor thread
676  Q_EMIT stopExecutor();
677  thread.wait();
678  }
679 }
680 
681 static QString categoryClass(int category)
682 {
683  switch(category)
684  {
685  case RPCConsole::CMD_REQUEST: return "cmd-request"; break;
686  case RPCConsole::CMD_REPLY: return "cmd-reply"; break;
687  case RPCConsole::CMD_ERROR: return "cmd-error"; break;
688  default: return "misc";
689  }
690 }
691 
693 {
695 }
696 
698 {
700 }
701 
702 void RPCConsole::setFontSize(int newSize)
703 {
704  QSettings settings;
705 
706  //don't allow an insane font size
707  if (newSize < FONT_RANGE.width() || newSize > FONT_RANGE.height())
708  return;
709 
710  // temp. store the console content
711  QString str = ui->messagesWidget->toHtml();
712 
713  // replace font tags size in current content
714  str.replace(QString("font-size:%1pt").arg(consoleFontSize), QString("font-size:%1pt").arg(newSize));
715 
716  // store the new font size
717  consoleFontSize = newSize;
718  settings.setValue(fontSizeSettingsKey, consoleFontSize);
719 
720  // clear console (reset icon sizes, default stylesheet) and re-add the content
721  float oldPosFactor = 1.0 / ui->messagesWidget->verticalScrollBar()->maximum() * ui->messagesWidget->verticalScrollBar()->value();
722  clear(false);
723  ui->messagesWidget->setHtml(str);
724  ui->messagesWidget->verticalScrollBar()->setValue(oldPosFactor * ui->messagesWidget->verticalScrollBar()->maximum());
725 }
726 
727 void RPCConsole::clear(bool clearHistory)
728 {
729  ui->messagesWidget->clear();
730  if(clearHistory)
731  {
732  history.clear();
733  historyPtr = 0;
734  }
735  ui->lineEdit->clear();
736  ui->lineEdit->setFocus();
737 
738  // Add smoothly scaled icon images.
739  // (when using width/height on an img, Qt uses nearest instead of linear interpolation)
740  for(int i=0; ICON_MAPPING[i].url; ++i)
741  {
742  ui->messagesWidget->document()->addResource(
743  QTextDocument::ImageResource,
744  QUrl(ICON_MAPPING[i].url),
745  platformStyle->TableColorImage(ICON_MAPPING[i].source, ICON_MAPPING[i].type).scaled(QSize(consoleFontSize*2, consoleFontSize*2), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
746  }
747 
748  // Set default style sheet
749  QFontInfo fixedFontInfo(GUIUtil::fixedPitchFont());
750  ui->messagesWidget->document()->setDefaultStyleSheet(
751  QString(
752  "table { }"
753  "td.time { color: #808080; font-size: %2; padding-top: 3px; } "
754  "td.message { font-family: %1; font-size: %2; white-space:pre-wrap; } "
755  "td.cmd-request { color: #006060; } "
756  "td.cmd-error { color: red; } "
757  ".secwarning { color: red; }"
758  "b { color: #006060; } "
759  ).arg(fixedFontInfo.family(), QString("%1pt").arg(consoleFontSize))
760  );
761 
762 #ifdef Q_OS_MAC
763  QString clsKey = "(⌘)-L";
764 #else
765  QString clsKey = "Ctrl-L";
766 #endif
767 
768  message(CMD_REPLY, (tr("Welcome to the %1 RPC console.").arg(tr(PACKAGE_NAME)) + "<br>" +
769  tr("Use up and down arrows to navigate history, and %1 to clear screen.").arg("<b>"+clsKey+"</b>") + "<br>" +
770  tr("Type <b>help</b> for an overview of available commands.")) +
771  "<br><span class=\"secwarning\">" +
772  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.") +
773  "</span>",
774  true);
775 }
776 
777 void RPCConsole::keyPressEvent(QKeyEvent *event)
778 {
779  if(windowType() != Qt::Widget && event->key() == Qt::Key_Escape)
780  {
781  close();
782  }
783 }
784 
785 void RPCConsole::message(int category, const QString &message, bool html)
786 {
787  QTime time = QTime::currentTime();
788  QString timeString = time.toString();
789  QString out;
790  out += "<table><tr><td class=\"time\" width=\"65\">" + timeString + "</td>";
791  out += "<td class=\"icon\" width=\"32\"><img src=\"" + categoryClass(category) + "\"></td>";
792  out += "<td class=\"message " + categoryClass(category) + "\" valign=\"middle\">";
793  if(html)
794  out += message;
795  else
796  out += GUIUtil::HtmlEscape(message, false);
797  out += "</td></tr></table>";
798  ui->messagesWidget->append(out);
799 }
800 
802 {
803  QString connections = QString::number(clientModel->getNumConnections()) + " (";
804  connections += tr("In:") + " " + QString::number(clientModel->getNumConnections(CONNECTIONS_IN)) + " / ";
805  connections += tr("Out:") + " " + QString::number(clientModel->getNumConnections(CONNECTIONS_OUT)) + ")";
806 
807  if(!clientModel->getNetworkActive()) {
808  connections += " (" + tr("Network activity disabled") + ")";
809  }
810 
811  ui->numberOfConnections->setText(connections);
812 }
813 
815 {
816  if (!clientModel)
817  return;
818 
820 }
821 
822 void RPCConsole::setNetworkActive(bool networkActive)
823 {
825 }
826 
827 void RPCConsole::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers)
828 {
829  if (!headers) {
830  ui->numberOfBlocks->setText(QString::number(count));
831  ui->lastBlockTime->setText(blockDate.toString());
832  }
833 }
834 
835 void RPCConsole::setMempoolSize(long numberOfTxs, size_t dynUsage)
836 {
837  ui->mempoolNumberTxs->setText(QString::number(numberOfTxs));
838 
839  if (dynUsage < 1000000)
840  ui->mempoolSize->setText(QString::number(dynUsage/1000.0, 'f', 2) + " KB");
841  else
842  ui->mempoolSize->setText(QString::number(dynUsage/1000000.0, 'f', 2) + " MB");
843 }
844 
846 {
847  QString cmd = ui->lineEdit->text();
848 
849  if(!cmd.isEmpty())
850  {
851  std::string strFilteredCmd;
852  try {
853  std::string dummy;
854  if (!RPCParseCommandLine(dummy, cmd.toStdString(), false, &strFilteredCmd)) {
855  // Failed to parse command, so we cannot even filter it for the history
856  throw std::runtime_error("Invalid command line");
857  }
858  } catch (const std::exception& e) {
859  QMessageBox::critical(this, "Error", QString("Error: ") + QString::fromStdString(e.what()));
860  return;
861  }
862 
863  ui->lineEdit->clear();
864 
865  cmdBeforeBrowsing = QString();
866 
867  message(CMD_REQUEST, QString::fromStdString(strFilteredCmd));
868  Q_EMIT cmdRequest(cmd);
869 
870  cmd = QString::fromStdString(strFilteredCmd);
871 
872  // Remove command, if already in history
873  history.removeOne(cmd);
874  // Append command to history
875  history.append(cmd);
876  // Enforce maximum history size
877  while(history.size() > CONSOLE_HISTORY)
878  history.removeFirst();
879  // Set pointer to end of history
880  historyPtr = history.size();
881 
882  // Scroll console view to end
883  scrollToEnd();
884  }
885 }
886 
888 {
889  // store current text when start browsing through the history
890  if (historyPtr == history.size()) {
891  cmdBeforeBrowsing = ui->lineEdit->text();
892  }
893 
894  historyPtr += offset;
895  if(historyPtr < 0)
896  historyPtr = 0;
897  if(historyPtr > history.size())
898  historyPtr = history.size();
899  QString cmd;
900  if(historyPtr < history.size())
901  cmd = history.at(historyPtr);
902  else if (!cmdBeforeBrowsing.isNull()) {
903  cmd = cmdBeforeBrowsing;
904  }
905  ui->lineEdit->setText(cmd);
906 }
907 
909 {
910  RPCExecutor *executor = new RPCExecutor();
911  executor->moveToThread(&thread);
912 
913  // Replies from executor object must go to this object
914  connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString)));
915  // Requests from this object must go to executor
916  connect(this, SIGNAL(cmdRequest(QString)), executor, SLOT(request(QString)));
917 
918  // On stopExecutor signal
919  // - quit the Qt event loop in the execution thread
920  connect(this, SIGNAL(stopExecutor()), &thread, SLOT(quit()));
921  // - queue executor for deletion (in execution thread)
922  connect(&thread, SIGNAL(finished()), executor, SLOT(deleteLater()), Qt::DirectConnection);
923 
924  // Default implementation of QThread::run() simply spins up an event loop in the thread,
925  // which is what we want.
926  thread.start();
927 }
928 
930 {
931  if (ui->tabWidget->widget(index) == ui->tab_console)
932  ui->lineEdit->setFocus();
933  else if (ui->tabWidget->widget(index) != ui->tab_peers)
935 }
936 
938 {
940 }
941 
943 {
944  QScrollBar *scrollbar = ui->messagesWidget->verticalScrollBar();
945  scrollbar->setValue(scrollbar->maximum());
946 }
947 
949 {
950  const int multiplier = 5; // each position on the slider represents 5 min
951  int mins = value * multiplier;
952  setTrafficGraphRange(mins);
953 }
954 
956 {
957  if(bytes < 1024)
958  return QString(tr("%1 B")).arg(bytes);
959  if(bytes < 1024 * 1024)
960  return QString(tr("%1 KB")).arg(bytes / 1024);
961  if(bytes < 1024 * 1024 * 1024)
962  return QString(tr("%1 MB")).arg(bytes / 1024 / 1024);
963 
964  return QString(tr("%1 GB")).arg(bytes / 1024 / 1024 / 1024);
965 }
966 
968 {
970  ui->lblGraphRange->setText(GUIUtil::formatDurationStr(mins * 60));
971 }
972 
973 void RPCConsole::updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut)
974 {
975  ui->lblBytesIn->setText(FormatBytes(totalBytesIn));
976  ui->lblBytesOut->setText(FormatBytes(totalBytesOut));
977 }
978 
979 void RPCConsole::peerSelected(const QItemSelection &selected, const QItemSelection &deselected)
980 {
981  Q_UNUSED(deselected);
982 
983  if (!clientModel || !clientModel->getPeerTableModel() || selected.indexes().isEmpty())
984  return;
985 
986  const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(selected.indexes().first().row());
987  if (stats)
988  updateNodeDetail(stats);
989 }
990 
992 {
993  QModelIndexList selected = ui->peerWidget->selectionModel()->selectedIndexes();
994  cachedNodeids.clear();
995  for(int i = 0; i < selected.size(); i++)
996  {
997  const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(selected.at(i).row());
998  cachedNodeids.append(stats->nodeStats.nodeid);
999  }
1000 }
1001 
1003 {
1005  return;
1006 
1007  const CNodeCombinedStats *stats = nullptr;
1008  bool fUnselect = false;
1009  bool fReselect = false;
1010 
1011  if (cachedNodeids.empty()) // no node selected yet
1012  return;
1013 
1014  // find the currently selected row
1015  int selectedRow = -1;
1016  QModelIndexList selectedModelIndex = ui->peerWidget->selectionModel()->selectedIndexes();
1017  if (!selectedModelIndex.isEmpty()) {
1018  selectedRow = selectedModelIndex.first().row();
1019  }
1020 
1021  // check if our detail node has a row in the table (it may not necessarily
1022  // be at selectedRow since its position can change after a layout change)
1023  int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(cachedNodeids.first());
1024 
1025  if (detailNodeRow < 0)
1026  {
1027  // detail node disappeared from table (node disconnected)
1028  fUnselect = true;
1029  }
1030  else
1031  {
1032  if (detailNodeRow != selectedRow)
1033  {
1034  // detail node moved position
1035  fUnselect = true;
1036  fReselect = true;
1037  }
1038 
1039  // get fresh stats on the detail node.
1040  stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow);
1041  }
1042 
1043  if (fUnselect && selectedRow >= 0) {
1045  }
1046 
1047  if (fReselect)
1048  {
1049  for(int i = 0; i < cachedNodeids.size(); i++)
1050  {
1052  }
1053  }
1054 
1055  if (stats)
1056  updateNodeDetail(stats);
1057 }
1058 
1060 {
1061  // update the detail ui with latest node information
1062  QString peerAddrDetails(QString::fromStdString(stats->nodeStats.addrName) + " ");
1063  peerAddrDetails += tr("(node id: %1)").arg(QString::number(stats->nodeStats.nodeid));
1064  if (!stats->nodeStats.addrLocal.empty())
1065  peerAddrDetails += "<br />" + tr("via %1").arg(QString::fromStdString(stats->nodeStats.addrLocal));
1066  ui->peerHeading->setText(peerAddrDetails);
1070  ui->peerBytesSent->setText(FormatBytes(stats->nodeStats.nSendBytes));
1071  ui->peerBytesRecv->setText(FormatBytes(stats->nodeStats.nRecvBytes));
1077  ui->peerVersion->setText(QString("%1").arg(QString::number(stats->nodeStats.nVersion)));
1078  ui->peerSubversion->setText(QString::fromStdString(stats->nodeStats.cleanSubVer));
1079  ui->peerDirection->setText(stats->nodeStats.fInbound ? tr("Inbound") : tr("Outbound"));
1080  ui->peerHeight->setText(QString("%1").arg(QString::number(stats->nodeStats.nStartingHeight)));
1081  ui->peerWhitelisted->setText(stats->nodeStats.fWhitelisted ? tr("Yes") : tr("No"));
1082 
1083  // This check fails for example if the lock was busy and
1084  // nodeStateStats couldn't be fetched.
1085  if (stats->fNodeStateStatsAvailable) {
1086  // Ban score is init to 0
1087  ui->peerBanScore->setText(QString("%1").arg(stats->nodeStateStats.nMisbehavior));
1088 
1089  // Sync height is init to -1
1090  if (stats->nodeStateStats.nSyncHeight > -1)
1091  ui->peerSyncHeight->setText(QString("%1").arg(stats->nodeStateStats.nSyncHeight));
1092  else
1093  ui->peerSyncHeight->setText(tr("Unknown"));
1094 
1095  // Common height is init to -1
1096  if (stats->nodeStateStats.nCommonHeight > -1)
1097  ui->peerCommonHeight->setText(QString("%1").arg(stats->nodeStateStats.nCommonHeight));
1098  else
1099  ui->peerCommonHeight->setText(tr("Unknown"));
1100  }
1101 
1102  ui->detailWidget->show();
1103 }
1104 
1105 void RPCConsole::resizeEvent(QResizeEvent *event)
1106 {
1107  QWidget::resizeEvent(event);
1108 }
1109 
1110 void RPCConsole::showEvent(QShowEvent *event)
1111 {
1112  QWidget::showEvent(event);
1113 
1115  return;
1116 
1117  // start PeerTableModel auto refresh
1119 }
1120 
1121 void RPCConsole::hideEvent(QHideEvent *event)
1122 {
1123  QWidget::hideEvent(event);
1124 
1126  return;
1127 
1128  // stop PeerTableModel auto refresh
1130 }
1131 
1132 void RPCConsole::showPeersTableContextMenu(const QPoint& point)
1133 {
1134  QModelIndex index = ui->peerWidget->indexAt(point);
1135  if (index.isValid())
1136  peersTableContextMenu->exec(QCursor::pos());
1137 }
1138 
1139 void RPCConsole::showBanTableContextMenu(const QPoint& point)
1140 {
1141  QModelIndex index = ui->banlistWidget->indexAt(point);
1142  if (index.isValid())
1143  banTableContextMenu->exec(QCursor::pos());
1144 }
1145 
1147 {
1148  if(!g_connman)
1149  return;
1150 
1151  // Get selected peer addresses
1152  QList<QModelIndex> nodes = GUIUtil::getEntryData(ui->peerWidget, PeerTableModel::NetNodeId);
1153  for(int i = 0; i < nodes.count(); i++)
1154  {
1155  // Get currently selected peer address
1156  NodeId id = nodes.at(i).data().toLongLong();
1157  // Find the node, disconnect it and clear the selected node
1158  if(g_connman->DisconnectNode(id))
1160  }
1161 }
1162 
1164 {
1165  if (!clientModel || !g_connman)
1166  return;
1167 
1168  // Get selected peer addresses
1169  QList<QModelIndex> nodes = GUIUtil::getEntryData(ui->peerWidget, PeerTableModel::NetNodeId);
1170  for(int i = 0; i < nodes.count(); i++)
1171  {
1172  // Get currently selected peer address
1173  NodeId id = nodes.at(i).data().toLongLong();
1174 
1175  // Get currently selected peer address
1176  int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(id);
1177  if(detailNodeRow < 0)
1178  return;
1179 
1180  // Find possible nodes, ban it and clear the selected node
1181  const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow);
1182  if(stats) {
1183  g_connman->Ban(stats->nodeStats.addr, BanReasonManuallyAdded, bantime);
1184  }
1185  }
1188 }
1189 
1191 {
1192  if (!clientModel)
1193  return;
1194 
1195  // Get selected ban addresses
1196  QList<QModelIndex> nodes = GUIUtil::getEntryData(ui->banlistWidget, BanTableModel::Address);
1197  for(int i = 0; i < nodes.count(); i++)
1198  {
1199  // Get currently selected ban address
1200  QString strNode = nodes.at(i).data().toString();
1201  CSubNet possibleSubnet;
1202 
1203  LookupSubNet(strNode.toStdString().c_str(), possibleSubnet);
1204  if (possibleSubnet.IsValid() && g_connman)
1205  {
1206  g_connman->Unban(possibleSubnet);
1208  }
1209  }
1210 }
1211 
1213 {
1214  ui->peerWidget->selectionModel()->clearSelection();
1215  cachedNodeids.clear();
1216  ui->detailWidget->hide();
1217  ui->peerHeading->setText(tr("Select a peer to view detailed information."));
1218 }
1219 
1221 {
1222  if (!clientModel)
1223  return;
1224 
1225  bool visible = clientModel->getBanTableModel()->shouldShow();
1226  ui->banlistWidget->setVisible(visible);
1227  ui->banHeading->setVisible(visible);
1228 }
1229 
1231 {
1232  ui->tabWidget->setCurrentIndex(tabType);
1233 }
void openDebugLogfile()
Definition: guiutil.cpp:422
UniValue execute(const JSONRPCRequest &request) const
Execute a method.
Definition: server.cpp:512
QTableView * banlistWidget
int getRowByNodeId(NodeId nodeid)
QTableView * peerWidget
const char * Name()
Implementation name.
Definition: rpcconsole.cpp:123
QLabel * peerPingTime
RPCTimerBase * NewTimer(std::function< void(void)> &func, int64_t millis)
Factory function for timers.
Definition: rpcconsole.cpp:124
const std::string & get_str() const
#define SetObjectStyleSheet(object, name)
Definition: styleSheet.h:10
int nStartingHeight
Definition: net.h:534
Local Fabcoin RPC console.
Definition: rpcconsole.h:31
RPC timer "driver".
Definition: server.h:157
QLabel * berkeleyDBVersion
#define function(a, b, c, d, k, s)
std::vector< std::string > listCommands() const
Returns a list of registered commands.
Definition: server.cpp:543
void keyPressEvent(QKeyEvent *)
Definition: rpcconsole.cpp:777
std::vector< CWalletRef > vpwallets
Definition: wallet.cpp:41
QLabel * clientVersion
QString cmdBeforeBrowsing
Definition: rpcconsole.h:146
QFont fixedPitchFont()
Definition: guiutil.cpp:90
CNodeStateStats nodeStateStats
QList< QModelIndex > getEntryData(QAbstractItemView *view, int column)
Return a field of the currently selected entry as a QString.
Definition: guiutil.cpp:302
QLabel * lblGraphRange
static QString FormatBytes(quint64 bytes)
Definition: rpcconsole.cpp:955
int64_t nTimeOffset
Definition: net.h:528
void showEvent(QShowEvent *event)
QPushButton * openDebugLogfileButton
QLabel * peerLastRecv
void on_lineEdit_returnPressed()
Definition: rpcconsole.cpp:845
QLabel * numberOfConnections
#define PACKAGE_NAME
QLabel * peerServices
QLabel * networkName
double getVerificationProgress(const CBlockIndex *tip) const
void message(int category, const QString &message, bool html=false)
Append the message to the message widget.
Definition: rpcconsole.cpp:785
static bool RPCExecuteCommandLine(std::string &strResult, const std::string &strCommand, std::string *const pstrFilteredOut=nullptr)
Definition: rpcconsole.h:40
void showPeersTableContextMenu(const QPoint &point)
Show custom context menu on Peers tab.
RPCConsole(const PlatformStyle *platformStyle, QWidget *parent)
Definition: rpcconsole.cpp:424
QStringList history
Definition: rpcconsole.h:144
QLabel * peerCommonHeight
quint64 getTotalBytesRecv() const
size_t count
Definition: ExecStats.cpp:37
QTextEdit * messagesWidget
bool getNetworkActive() const
Return true if network activity in core is enabled.
QThread thread
Definition: rpcconsole.h:154
QLabel * peerBanScore
ServiceFlags nServices
Definition: net.h:523
QLabel * banHeading
int getNumConnections(unsigned int flags=CONNECTIONS_ALL) const
Return number of connections, default is in- and outbound (total)
Definition: clientmodel.cpp:57
void setNetworkActive(bool networkActive)
Set network state shown in the UI.
Definition: rpcconsole.cpp:822
void scrollToEnd()
Scroll console view to end.
Definition: rpcconsole.cpp:942
QString formatTimeOffset(int64_t nTimeOffset)
Definition: guiutil.cpp:937
bool isArray() const
Definition: univalue.h:85
QLabel * peerDirection
std::string cleanSubVer
Definition: net.h:531
void clearSelectedNode()
clear the selected node
QLabel * peerHeading
int64_t nTimeConnected
Definition: net.h:527
assert(len-trim+(2 *lenIndices)<=WIDTH)
QString HtmlEscape(const QString &str, bool fMultiLine)
Definition: guiutil.cpp:258
QWidget * detailWidget
QLabel * peerVersion
void fontSmaller()
Definition: rpcconsole.cpp:697
QLabel * startupTime
QString formatClientStartupTime() const
PeerTableModel * getPeerTableModel()
void disconnectSelectedNode()
Disconnect a selected node on the Peers tab.
CNodeStats nodeStats
void on_tabWidget_currentChanged(int index)
Definition: rpcconsole.cpp:929
bytes code
Definition: SmartVM.cpp:45
QLabel * peerHeight
void setupUi(QWidget *RPCConsole)
QLabel * clientUserAgent
QLabel * mempoolNumberTxs
void version()
Definition: main.cpp:53
void updateNodeDetail(const CNodeCombinedStats *stats)
show detailed information on ui about selected node
void RPCUnsetTimerInterface(RPCTimerInterface *iface)
Unset factory function for timers.
Definition: server.cpp:576
QLabel * peerConnTime
QString dataDir() const
QPushButton * btnClearTrafficGraph
QLabel * timeoffset
UniValue RPCConvertValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Convert positional arguments to command-specific RPC representation.
Definition: client.cpp:245
void setClientModel(ClientModel *model)
Definition: rpcconsole.cpp:545
void resizeEvent(QResizeEvent *event)
std::string strMethod
Definition: server.h:58
QLabel * peerSubversion
const char * url
Definition: rpcconsole.cpp:59
void reply(int category, const QString &command)
QPushButton * fontSmallerButton
QLabel * peerLastSend
QLabel * numberOfBlocks
QMenu * peersTableContextMenu
Definition: rpcconsole.h:150
CRPCTable tableRPC
Definition: server.cpp:599
QLabel * peerMinPing
int nVersion
Definition: net.h:530
const char * source
Definition: rpcconsole.cpp:60
void browseHistory(int offset)
Go forward or back in history.
Definition: rpcconsole.cpp:887
bool push_back(const UniValue &val)
Definition: univalue.cpp:110
int64_t GetSystemTimeInSeconds()
Definition: utiltime.cpp:55
Class for handling RPC timers (used for e.g.
Definition: rpcconsole.cpp:100
QString formatDurationStr(int secs)
Definition: guiutil.cpp:874
UniValue params
Definition: server.h:59
std::function< void(void)> func
Definition: rpcconsole.cpp:116
const int CONSOLE_HISTORY
Definition: rpcconsole.cpp:53
QDateTime getLastBlockDate() const
QPushButton * clearButton
const Object_type::value_type::Value_type & find_value(const Object_type &obj, const String_type &name)
QLabel * lblBytesOut
QPushButton * promptIcon
QtRPCTimerBase(std::function< void(void)> &_func, int64_t millis)
Definition: rpcconsole.cpp:104
QLineEdit * lineEdit
QLabel * lastBlockTime
void setTabFocus(enum TabTypes tabType)
set which tab has the focus (is visible)
void request(const QString &command)
Definition: rpcconsole.cpp:392
QLabel * peerSyncHeight
QString formatSubVersion() const
std::vector< byte > bytes
Definition: Common.h:75
bool fInbound
Definition: net.h:532
BanTableModel * getBanTableModel()
const struct @57 ICON_MAPPING[]
uint64_t nRecvBytes
Definition: net.h:537
int historyPtr
Definition: rpcconsole.h:145
void peerLayoutChanged()
Handle updated peer information.
RPCTimerInterface * rpcTimerInterface
Definition: rpcconsole.h:149
double dPingTime
Definition: net.h:540
std::string addrName
Definition: net.h:529
static bool RPCParseCommandLine(std::string &strResult, const std::string &strCommand, bool fExecute, std::string *const pstrFilteredOut=nullptr)
Split shell command line into a list of arguments and optionally execute the command(s).
Definition: rpcconsole.cpp:152
void updateNetworkState()
Update UI with latest network info from model.
Definition: rpcconsole.cpp:801
int64_t NodeId
Definition: net.h:93
const CNodeCombinedStats * getNodeStats(int idx)
uint64_t nSendBytes
Definition: net.h:535
void on_openDebugLogfileButton_clicked()
open the debug.log from the current datadir
Definition: rpcconsole.cpp:937
Model for Fabcoin network client.
Definition: clientmodel.h:38
QLabel * peerWhitelisted
void unbanSelectedNode()
Unban a selected node on the Bans tab.
QLabel * label_berkeleyDBVersion
QLabel * peerBytesRecv
QLabel * dataDir
void hideEvent(QHideEvent *event)
ClientModel * clientModel
Definition: rpcconsole.h:143
TrafficGraphWidget * trafficGraph
QString formatPingTime(double dPingTime)
Definition: guiutil.cpp:932
void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface)
Set the factory function for timer, but only, if unset.
Definition: server.cpp:565
virtual bool eventFilter(QObject *obj, QEvent *event)
Definition: rpcconsole.cpp:501
QMenu * banTableContextMenu
Definition: rpcconsole.h:151
bool LookupSubNet(const char *pszName, CSubNet &ret)
Definition: netbase.cpp:660
void setTrafficGraphRange(int mins)
Definition: rpcconsole.cpp:967
int getNumBlocks() const
Definition: clientmodel.cpp:73
QLabel * peerBytesSent
void clear(bool clearHistory=true)
Definition: rpcconsole.cpp:727
void showOrHideBanTableIfRequired()
Hides ban table if no bans are present.
void fontBigger()
Definition: rpcconsole.cpp:692
QLabel * lblBytesIn
QWidget * tab_peers
quint64 getTotalBytesSent() const
void updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut)
update traffic statistics
Definition: rpcconsole.cpp:973
QLabel * peerPingWait
QList< NodeId > cachedNodeids
Definition: rpcconsole.h:147
void setMempoolSize(long numberOfTxs, size_t dynUsage)
Set size (number of transactions and memory usage) of the mempool in the UI.
Definition: rpcconsole.cpp:835
void setFontSize(int newSize)
Definition: rpcconsole.cpp:702
bool IsValid() const
Definition: netaddress.cpp:721
void setNumConnections(int count)
Set number of connections shown in the UI.
Definition: rpcconsole.cpp:814
PlatformStyle::TableColorType type
Definition: rpcconsole.cpp:61
void startExecutor()
Definition: rpcconsole.cpp:908
QIcon MultiStatesIcon(const QString &resourcename, StateType type=NavBar, QColor color=Qt::white, QColor colorAlt=0x2d2d2d) const
Get multi-states icon.
const CChainParams & Params()
Return the currently selected parameters.
void peerLayoutAboutToChange()
Handle selection caching before update.
Definition: rpcconsole.cpp:991
QString formatServicesStr(quint64 mask)
Definition: guiutil.cpp:894
std::string addrLocal
Definition: net.h:544
void on_sldGraphRange_valueChanged(int value)
change the time range of the network traffic graph
Definition: rpcconsole.cpp:948
std::string URI
Definition: server.h:61
QImage TableColorImage(const QString &resourcename, TableColorType type) const
void banSelectedNode(int bantime)
Ban a selected node on the Peers tab.
double dMinPing
Definition: net.h:542
Opaque base class for timers returned by NewTimerFunc.
Definition: server.h:148
QWidget * tab_console
const int INITIAL_TRAFFIC_GRAPH_MINS
Definition: rpcconsole.cpp:54
QLabel * mempoolSize
std::unique_ptr< CConnman > g_connman
Definition: init.cpp:75
const char fontSizeSettingsKey[]
Definition: rpcconsole.cpp:56
#define e(i)
Definition: sha.cpp:733
void setGraphRangeMins(int mins)
void peerSelected(const QItemSelection &selected, const QItemSelection &deselected)
Handle selection of peer in peers list.
Definition: rpcconsole.cpp:979
int consoleFontSize
Definition: rpcconsole.h:152
bool getImagesOnButtons() const
Definition: platformstyle.h:21
bool isObject() const
Definition: univalue.h:86
const QSize FONT_RANGE(4, 40)
void clear()
Definition: univalue.cpp:17
QTabWidget * tabWidget
bool fWhitelisted
Definition: net.h:539
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
uint32_t ch(uint32_t x, uint32_t y, uint32_t z)
Definition: picosha2.h:73
Ui::RPCConsole * ui
Definition: rpcconsole.h:142
QPushButton * fontBiggerButton
QCompleter * autoCompleter
Definition: rpcconsole.h:153
void stopExecutor()
double dPingWait
Definition: net.h:541
QString formatFullVersion() const
void cmdRequest(const QString &command)
bool isStr() const
Definition: univalue.h:83
int64_t nLastSend
Definition: net.h:525
const PlatformStyle * platformStyle
Definition: rpcconsole.h:148
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:827
int atoi(const std::string &str)
NodeId nodeid
Definition: net.h:522
void setClientModel(ClientModel *model)
void showBanTableContextMenu(const QPoint &point)
Show custom context menu on Bans tab.
int64_t nLastRecv
Definition: net.h:526
CAddress addr
Definition: net.h:546