Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13115022
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
25 KB
Subscribers
None
View Options
diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui
index be0f4ebe9..2d8237f36 100644
--- a/src/qt/forms/rpcconsole.ui
+++ b/src/qt/forms/rpcconsole.ui
@@ -1,430 +1,456 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>RPCConsole</class>
<widget class="QDialog" name="RPCConsole">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>740</width>
<height>450</height>
</rect>
</property>
<property name="windowTitle">
<string>Bitcoin debug window</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab_info">
<attribute name="title">
<string>&Information</string>
</attribute>
<layout class="QGridLayout" name="gridLayout" columnstretch="0,1">
<property name="horizontalSpacing">
<number>12</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_9">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Client</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Client name</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="clientName">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
<string>N/A</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Client version</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="clientVersion">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
<string>N/A</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="0">
+ <widget class="QLabel" name="label_14">
+ <property name="text">
+ <string>Using OpenSSL version</string>
+ </property>
+ <property name="indent">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLabel" name="openSSLVersion">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
+ </property>
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string>Build date</string>
</property>
</widget>
</item>
- <item row="3" column="1">
+ <item row="4" column="1">
<widget class="QLabel" name="buildDate">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
<string>N/A</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
- <item row="4" column="0">
+ <item row="5" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Startup time</string>
</property>
</widget>
</item>
- <item row="4" column="1">
+ <item row="5" column="1">
<widget class="QLabel" name="startupTime">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
<string>N/A</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
- <item row="5" column="0">
+ <item row="6" column="0">
<widget class="QLabel" name="label_11">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Network</string>
</property>
</widget>
</item>
- <item row="6" column="0">
+ <item row="7" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Number of connections</string>
</property>
</widget>
</item>
- <item row="6" column="1">
+ <item row="7" column="1">
<widget class="QLabel" name="numberOfConnections">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
<string>N/A</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
- <item row="7" column="0">
+ <item row="8" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>On testnet</string>
</property>
</widget>
</item>
- <item row="7" column="1">
+ <item row="8" column="1">
<widget class="QCheckBox" name="isTestNet">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
- <item row="8" column="0">
+ <item row="9" column="0">
<widget class="QLabel" name="label_10">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Block chain</string>
</property>
</widget>
</item>
- <item row="9" column="0">
+ <item row="10" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Current number of blocks</string>
</property>
</widget>
</item>
- <item row="9" column="1">
+ <item row="10" column="1">
<widget class="QLabel" name="numberOfBlocks">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
<string>N/A</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
- <item row="10" column="0">
+ <item row="11" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Estimated total blocks</string>
</property>
</widget>
</item>
- <item row="10" column="1">
+ <item row="11" column="1">
<widget class="QLabel" name="totalBlocks">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
<string>N/A</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
- <item row="11" column="0">
+ <item row="12" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Last block time</string>
</property>
</widget>
</item>
- <item row="11" column="1">
+ <item row="12" column="1">
<widget class="QLabel" name="lastBlockTime">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
<string>N/A</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
- <item row="12" column="0">
+ <item row="13" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
- <item row="13" column="0">
+ <item row="14" column="0">
<widget class="QLabel" name="labelDebugLogfile">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Debug logfile</string>
</property>
</widget>
</item>
- <item row="14" column="0">
+ <item row="15" column="0">
<widget class="QPushButton" name="openDebugLogfileButton">
<property name="toolTip">
<string>Open the Bitcoin debug logfile from the current data directory. This can take a few seconds for large logfiles.</string>
</property>
<property name="text">
<string>&Open</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
- <item row="15" column="0">
+ <item row="16" column="0">
<widget class="QLabel" name="labelCLOptions">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Command-line options</string>
</property>
</widget>
</item>
- <item row="16" column="0">
+ <item row="17" column="0">
<widget class="QPushButton" name="showCLOptionsButton">
<property name="toolTip">
<string>Show the Bitcoin-Qt help message to get a list with possible Bitcoin command-line options.</string>
</property>
<property name="text">
<string>&Show</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
- <item row="17" column="0">
+ <item row="18" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_console">
<attribute name="title">
<string>&Console</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>3</number>
</property>
<item>
<widget class="QTextEdit" name="messagesWidget">
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="tabKeyNavigation" stdset="0">
<bool>false</bool>
</property>
<property name="columnCount" stdset="0">
<number>2</number>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>3</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string notr="true">></string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit"/>
</item>
<item>
<widget class="QPushButton" name="clearButton">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string>Clear console</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../bitcoin.qrc">
<normaloff>:/icons/remove</normaloff>:/icons/remove</iconset>
</property>
<property name="shortcut">
<string notr="true">Ctrl+L</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../bitcoin.qrc"/>
</resources>
<connections/>
</ui>
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 7b40db076..08f936e71 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -1,331 +1,335 @@
#include "rpcconsole.h"
#include "ui_rpcconsole.h"
#include "clientmodel.h"
#include "bitcoinrpc.h"
#include "guiutil.h"
#include <QTime>
#include <QTimer>
#include <QThread>
#include <QTextEdit>
#include <QKeyEvent>
#include <QUrl>
#include <QScrollBar>
#include <boost/tokenizer.hpp>
+#include <openssl/crypto.h>
// TODO: make it possible to filter out categories (esp debug messages when implemented)
// TODO: receive errors and debug messages through ClientModel
const int CONSOLE_SCROLLBACK = 50;
const int CONSOLE_HISTORY = 50;
const QSize ICON_SIZE(24, 24);
const struct {
const char *url;
const char *source;
} ICON_MAPPING[] = {
{"cmd-request", ":/icons/tx_input"},
{"cmd-reply", ":/icons/tx_output"},
{"cmd-error", ":/icons/tx_output"},
{"misc", ":/icons/tx_inout"},
{NULL, NULL}
};
/* Object for executing console RPC commands in a separate thread.
*/
class RPCExecutor: public QObject
{
Q_OBJECT
public slots:
void start();
void request(const QString &command);
signals:
void reply(int category, const QString &command);
};
#include "rpcconsole.moc"
void RPCExecutor::start()
{
// Nothing to do
}
void RPCExecutor::request(const QString &command)
{
// Parse shell-like command line into separate arguments
std::string strMethod;
std::vector<std::string> strParams;
try {
boost::escaped_list_separator<char> els('\\',' ','\"');
std::string strCommand = command.toStdString();
boost::tokenizer<boost::escaped_list_separator<char> > tok(strCommand, els);
int n = 0;
for(boost::tokenizer<boost::escaped_list_separator<char> >::iterator beg=tok.begin(); beg!=tok.end();++beg,++n)
{
if(n == 0) // First parameter is the command
strMethod = *beg;
else
strParams.push_back(*beg);
}
}
catch(boost::escaped_list_error &e)
{
emit reply(RPCConsole::CMD_ERROR, QString("Parse error"));
return;
}
try {
std::string strPrint;
json_spirit::Value result = tableRPC.execute(strMethod, RPCConvertValues(strMethod, strParams));
// Format result reply
if (result.type() == json_spirit::null_type)
strPrint = "";
else if (result.type() == json_spirit::str_type)
strPrint = result.get_str();
else
strPrint = write_string(result, true);
emit reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint));
}
catch (json_spirit::Object& objError)
{
emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(write_string(json_spirit::Value(objError), false)));
}
catch (std::exception& e)
{
emit reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what()));
}
}
RPCConsole::RPCConsole(QWidget *parent) :
QDialog(parent),
ui(new Ui::RPCConsole),
historyPtr(0)
{
ui->setupUi(this);
#ifndef Q_WS_MAC
ui->openDebugLogfileButton->setIcon(QIcon(":/icons/export"));
ui->showCLOptionsButton->setIcon(QIcon(":/icons/options"));
#endif
// Install event filter for up and down arrow
ui->lineEdit->installEventFilter(this);
connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
+ // set OpenSSL version label
+ ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION));
+
startExecutor();
clear();
}
RPCConsole::~RPCConsole()
{
emit stopExecutor();
delete ui;
}
bool RPCConsole::eventFilter(QObject* obj, QEvent *event)
{
if(obj == ui->lineEdit)
{
if(event->type() == QEvent::KeyPress)
{
QKeyEvent *key = static_cast<QKeyEvent*>(event);
switch(key->key())
{
case Qt::Key_Up: browseHistory(-1); return true;
case Qt::Key_Down: browseHistory(1); return true;
}
}
}
return QDialog::eventFilter(obj, event);
}
void RPCConsole::setClientModel(ClientModel *model)
{
this->clientModel = model;
if(model)
{
// Subscribe to information, replies, messages, errors
connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
connect(model, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int)));
// Provide initial values
ui->clientVersion->setText(model->formatFullVersion());
ui->clientName->setText(model->clientName());
ui->buildDate->setText(model->formatBuildDate());
ui->startupTime->setText(model->formatClientStartupTime());
setNumConnections(model->getNumConnections());
ui->isTestNet->setChecked(model->isTestNet());
setNumBlocks(model->getNumBlocks(), model->getNumBlocksOfPeers());
}
}
static QString categoryClass(int category)
{
switch(category)
{
case RPCConsole::CMD_REQUEST: return "cmd-request"; break;
case RPCConsole::CMD_REPLY: return "cmd-reply"; break;
case RPCConsole::CMD_ERROR: return "cmd-error"; break;
default: return "misc";
}
}
void RPCConsole::clear()
{
ui->messagesWidget->clear();
ui->lineEdit->clear();
ui->lineEdit->setFocus();
// Add smoothly scaled icon images.
// (when using width/height on an img, Qt uses nearest instead of linear interpolation)
for(int i=0; ICON_MAPPING[i].url; ++i)
{
ui->messagesWidget->document()->addResource(
QTextDocument::ImageResource,
QUrl(ICON_MAPPING[i].url),
QImage(ICON_MAPPING[i].source).scaled(ICON_SIZE, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
}
// Set default style sheet
ui->messagesWidget->document()->setDefaultStyleSheet(
"table { }"
"td.time { color: #808080; padding-top: 3px; } "
"td.message { font-family: Monospace; font-size: 12px; } "
"td.cmd-request { color: #006060; } "
"td.cmd-error { color: red; } "
"b { color: #006060; } "
);
message(CMD_REPLY, (tr("Welcome to the Bitcoin RPC console.") + "<br>" +
tr("Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen.") + "<br>" +
tr("Type <b>help</b> for an overview of available commands.")), true);
}
void RPCConsole::message(int category, const QString &message, bool html)
{
QTime time = QTime::currentTime();
QString timeString = time.toString();
QString out;
out += "<table><tr><td class=\"time\" width=\"65\">" + timeString + "</td>";
out += "<td class=\"icon\" width=\"32\"><img src=\"" + categoryClass(category) + "\"></td>";
out += "<td class=\"message " + categoryClass(category) + "\" valign=\"middle\">";
if(html)
out += message;
else
out += GUIUtil::HtmlEscape(message, true);
out += "</td></tr></table>";
ui->messagesWidget->append(out);
}
void RPCConsole::setNumConnections(int count)
{
ui->numberOfConnections->setText(QString::number(count));
}
void RPCConsole::setNumBlocks(int count, int countOfPeers)
{
ui->numberOfBlocks->setText(QString::number(count));
ui->totalBlocks->setText(QString::number(countOfPeers));
if(clientModel)
{
// If there is no current number available display N/A instead of 0, which can't ever be true
ui->totalBlocks->setText(clientModel->getNumBlocksOfPeers() == 0 ? tr("N/A") : QString::number(clientModel->getNumBlocksOfPeers()));
ui->lastBlockTime->setText(clientModel->getLastBlockDate().toString());
}
}
void RPCConsole::on_lineEdit_returnPressed()
{
QString cmd = ui->lineEdit->text();
ui->lineEdit->clear();
if(!cmd.isEmpty())
{
message(CMD_REQUEST, cmd);
emit cmdRequest(cmd);
// Truncate history from current position
history.erase(history.begin() + historyPtr, history.end());
// Append command to history
history.append(cmd);
// Enforce maximum history size
while(history.size() > CONSOLE_HISTORY)
history.removeFirst();
// Set pointer to end of history
historyPtr = history.size();
// Scroll console view to end
scrollToEnd();
}
}
void RPCConsole::browseHistory(int offset)
{
historyPtr += offset;
if(historyPtr < 0)
historyPtr = 0;
if(historyPtr > history.size())
historyPtr = history.size();
QString cmd;
if(historyPtr < history.size())
cmd = history.at(historyPtr);
ui->lineEdit->setText(cmd);
}
void RPCConsole::startExecutor()
{
QThread* thread = new QThread;
RPCExecutor *executor = new RPCExecutor();
executor->moveToThread(thread);
// Notify executor when thread started (in executor thread)
connect(thread, SIGNAL(started()), executor, SLOT(start()));
// Replies from executor object must go to this object
connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString)));
// Requests from this object must go to executor
connect(this, SIGNAL(cmdRequest(QString)), executor, SLOT(request(QString)));
// On stopExecutor signal
// - queue executor for deletion (in execution thread)
// - quit the Qt event loop in the execution thread
connect(this, SIGNAL(stopExecutor()), executor, SLOT(deleteLater()));
connect(this, SIGNAL(stopExecutor()), thread, SLOT(quit()));
// Queue the thread for deletion (in this thread) when it is finished
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
// Default implementation of QThread::run() simply spins up an event loop in the thread,
// which is what we want.
thread->start();
}
void RPCConsole::on_tabWidget_currentChanged(int index)
{
if(ui->tabWidget->widget(index) == ui->tab_console)
{
ui->lineEdit->setFocus();
}
}
void RPCConsole::on_openDebugLogfileButton_clicked()
{
GUIUtil::openDebugLogfile();
}
void RPCConsole::scrollToEnd()
{
QScrollBar *scrollbar = ui->messagesWidget->verticalScrollBar();
scrollbar->setValue(scrollbar->maximum());
}
void RPCConsole::on_showCLOptionsButton_clicked()
{
GUIUtil::HelpMessageBox help;
help.exec();
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Mar 2, 09:19 (1 d, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5185637
Default Alt Text
(25 KB)
Attached To
rABC Bitcoin ABC
Event Timeline
Log In to Comment