aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bitcoinrpc.cpp2
-rw-r--r--src/init.cpp12
-rw-r--r--src/makefile.unix15
-rw-r--r--src/net.cpp44
-rw-r--r--src/net.h3
-rw-r--r--src/netbase.cpp16
-rw-r--r--src/qt/forms/rpcconsole.ui22
-rw-r--r--src/qt/forms/transactiondescdialog.ui4
-rw-r--r--src/qt/rpcconsole.cpp151
-rw-r--r--src/qt/rpcconsole.h5
10 files changed, 135 insertions, 139 deletions
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index df3c190b38..e058978ebf 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -2447,7 +2447,7 @@ int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRe
strMessageRet = "";
// Read status
- int nProto;
+ int nProto = 0;
int nStatus = ReadHTTPStatus(stream, nProto);
// Read header
diff --git a/src/init.cpp b/src/init.cpp
index fe07ed7275..d253c3b7a6 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -192,7 +192,7 @@ bool AppInit2(int argc, char* argv[])
" -timeout=<n> \t " + _("Specify connection timeout (in milliseconds)") + "\n" +
" -proxy=<ip:port> \t " + _("Connect through socks proxy") + "\n" +
" -socks=<n> \t " + _("Select the version of socks proxy to use (4 or 5, 5 is default)") + "\n" +
- " -noproxy=<net> \t " + _("Do not use proxy for connections to network net (ipv4 or ipv6)") + "\n" +
+ " -noproxy=<net> \t " + _("Do not use proxy for connections to network <net> (IPv4 or IPv6)") + "\n" +
" -dns \t " + _("Allow DNS lookups for -addnode, -seednode and -connect") + "\n" +
" -proxydns \t " + _("Pass DNS requests to (SOCKS5) proxy") + "\n" +
" -port=<port> \t\t " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n" +
@@ -201,7 +201,7 @@ bool AppInit2(int argc, char* argv[])
" -connect=<ip> \t\t " + _("Connect only to the specified node") + "\n" +
" -seednode=<ip> \t\t " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n" +
" -externalip=<ip> \t " + _("Specify your own public address") + "\n" +
- " -blocknet=<net> \t " + _("Do not connect to addresses in network net (ipv4, ipv6)") + "\n" +
+ " -blocknet=<net> \t " + _("Do not connect to addresses in network <net> (IPv4 or IPv6)") + "\n" +
" -discover \t " + _("Try to discover public IP address (default: 1)") + "\n" +
" -irc \t " + _("Find peers using internet relay chat (default: 0)") + "\n" +
" -listen \t " + _("Accept connections from outside (default: 1)") + "\n" +
@@ -611,14 +611,14 @@ bool AppInit2(int argc, char* argv[])
std::string strError;
if (mapArgs.count("-bind")) {
BOOST_FOREACH(std::string strBind, mapMultiArgs["-bind"]) {
- fBound |= Bind(CService(strBind, GetDefaultPort(), false));
+ fBound |= Bind(CService(strBind, GetListenPort(), false));
}
} else {
struct in_addr inaddr_any;
inaddr_any.s_addr = INADDR_ANY;
- fBound |= Bind(CService(inaddr_any, GetDefaultPort()));
+ fBound |= Bind(CService(inaddr_any, GetListenPort()));
#ifdef USE_IPV6
- fBound |= Bind(CService(in6addr_any, GetDefaultPort()));
+ fBound |= Bind(CService(in6addr_any, GetListenPort()));
#endif
}
if (!fBound)
@@ -628,7 +628,7 @@ bool AppInit2(int argc, char* argv[])
if (mapArgs.count("-externalip"))
{
BOOST_FOREACH(string strAddr, mapMultiArgs["-externalip"])
- AddLocal(CNetAddr(strAddr, fNameLookup), LOCAL_MANUAL);
+ AddLocal(CService(strAddr, GetListenPort(), fNameLookup), LOCAL_MANUAL);
}
if (mapArgs.count("-paytxfee"))
diff --git a/src/makefile.unix b/src/makefile.unix
index ad0a82df50..b1cc89d0cb 100644
--- a/src/makefile.unix
+++ b/src/makefile.unix
@@ -82,8 +82,11 @@ LIBS+= \
DEBUGFLAGS=-g
-CXXFLAGS=-O2 -pthread -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter \
- $(DEBUGFLAGS) $(DEFS) $(HARDENING)
+
+# CXXFLAGS can be specified on the make command line, so we use xCXXFLAGS that only
+# adds some defaults in front. Unfortunately, CXXFLAGS=... $(CXXFLAGS) does not work.
+xCXXFLAGS=-O2 -pthread -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter \
+ $(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS)
OBJS= \
obj/version.o \
@@ -121,26 +124,26 @@ version.cpp: obj/build.h
DEFS += -DHAVE_BUILD_INFO
obj/%.o: %.cpp
- $(CXX) -c $(CXXFLAGS) -MMD -o $@ $<
+ $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $<
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
rm -f $(@:%.o=%.d)
bitcoind: $(OBJS:obj/%=obj/%)
- $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)
+ $(CXX) $(xCXXFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)
TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp))
obj-test/%.o: test/%.cpp
- $(CXX) -c $(TESTDEFS) $(CXXFLAGS) -MMD -o $@ $<
+ $(CXX) -c $(TESTDEFS) $(xCXXFLAGS) -MMD -o $@ $<
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
rm -f $(@:%.o=%.d)
test_bitcoin: $(TESTOBJS) $(filter-out obj/init.o,$(OBJS:obj/%=obj/%))
- $(CXX) $(CXXFLAGS) -o $@ $(LIBPATHS) $^ -Wl,-B$(LMODE) -lboost_unit_test_framework $(LDFLAGS) $(LIBS)
+ $(CXX) $(xCXXFLAGS) -o $@ $(LIBPATHS) $^ -Wl,-B$(LMODE) -lboost_unit_test_framework $(LDFLAGS) $(LIBS)
clean:
-rm -f bitcoind test_bitcoin
diff --git a/src/net.cpp b/src/net.cpp
index f12afb78e6..c8cb17091f 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -38,6 +38,10 @@ void ThreadDNSAddressSeed2(void* parg);
bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false);
+struct LocalServiceInfo {
+ int nScore;
+ int nPort;
+};
//
// Global state variables
@@ -46,7 +50,7 @@ bool fClient = false;
static bool fUseUPnP = false;
uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
static CCriticalSection cs_mapLocalHost;
-static map<CService, int> mapLocalHost;
+static map<CNetAddr, LocalServiceInfo> mapLocalHost;
static bool vfReachable[NET_MAX] = {};
static bool vfLimited[NET_MAX] = {};
static CNode* pnodeLocalHost = NULL;
@@ -98,23 +102,23 @@ bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
if (fUseProxy || mapArgs.count("-connect") || fNoListen)
return false;
- int nBestCount = -1;
+ int nBestScore = -1;
int nBestReachability = -1;
{
LOCK(cs_mapLocalHost);
- for (map<CService, int>::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
+ for (map<CNetAddr, LocalServiceInfo>::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
{
- int nCount = (*it).second;
+ int nScore = (*it).second.nScore;
int nReachability = (*it).first.GetReachabilityFrom(paddrPeer);
- if (nReachability > nBestReachability || (nReachability == nBestReachability && nCount > nBestCount))
+ if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
{
- addr = (*it).first;
+ addr = CService((*it).first, (*it).second.nPort);
nBestReachability = nReachability;
- nBestCount = nCount;
+ nBestScore = nScore;
}
}
}
- return nBestCount >= 0;
+ return nBestScore >= 0;
}
// get best local address for a particular peer as a CAddress
@@ -211,7 +215,12 @@ bool AddLocal(const CService& addr, int nScore)
{
LOCK(cs_mapLocalHost);
- mapLocalHost[addr] = std::max(nScore, mapLocalHost[addr]) + (mapLocalHost.count(addr) ? 1 : 0);
+ bool fAlready = mapLocalHost.count(addr) > 0;
+ LocalServiceInfo &info = mapLocalHost[addr];
+ if (!fAlready || nScore >= info.nScore) {
+ info.nScore = nScore;
+ info.nPort = addr.GetPort() + (fAlready ? 1 : 0);
+ }
enum Network net = addr.GetNetwork();
vfReachable[net] = true;
if (net == NET_IPV6) vfReachable[NET_IPV4] = true;
@@ -222,11 +231,9 @@ bool AddLocal(const CService& addr, int nScore)
return true;
}
-bool AddLocal(const CNetAddr& addr, int nScore, int port)
+bool AddLocal(const CNetAddr &addr, int nScore)
{
- if (port == -1)
- port = GetListenPort();
- return AddLocal(CService(addr, port), nScore);
+ return AddLocal(CService(addr, GetListenPort()), nScore);
}
/** Make a particular network entirely off-limits (no automatic connects to it) */
@@ -249,7 +256,7 @@ bool SeenLocal(const CService& addr)
LOCK(cs_mapLocalHost);
if (mapLocalHost.count(addr) == 0)
return false;
- mapLocalHost[addr]++;
+ mapLocalHost[addr].nScore++;
}
AdvertizeLocal();
@@ -1796,7 +1803,7 @@ void static Discover()
struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
CNetAddr addr(s4->sin_addr);
if (AddLocal(addr, LOCAL_IF))
- printf("ipv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
+ printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
}
#ifdef USE_IPV6
else if (ifa->ifa_addr->sa_family == AF_INET6)
@@ -1804,7 +1811,7 @@ void static Discover()
struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
CNetAddr addr(s6->sin6_addr);
if (AddLocal(addr, LOCAL_IF))
- printf("ipv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
+ printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
}
#endif
}
@@ -1887,8 +1894,9 @@ bool StopNode()
fShutdown = true;
nTransactionsUpdated++;
int64 nStart = GetTime();
- for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
- semOutbound->post();
+ if (semOutbound)
+ for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
+ semOutbound->post();
do
{
int nThreadsRunning = 0;
diff --git a/src/net.h b/src/net.h
index 8fe8c0047d..3755c765d3 100644
--- a/src/net.h
+++ b/src/net.h
@@ -38,6 +38,7 @@ CNode* FindNode(const CNetAddr& ip);
CNode* FindNode(const CService& ip);
CNode* ConnectNode(CAddress addrConnect, const char *strDest = NULL, int64 nTimeout=0);
void MapPort(bool fMapPort);
+unsigned short GetListenPort();
bool BindListenPort(const CService &bindAddr, std::string& strError=REF(std::string()));
void StartNode(void* parg);
bool StopNode();
@@ -58,7 +59,7 @@ enum
void SetLimited(enum Network net, bool fLimited = true);
bool IsLimited(const CNetAddr& addr);
bool AddLocal(const CService& addr, int nScore = LOCAL_NONE);
-bool AddLocal(const CNetAddr& addr, int nScore = LOCAL_NONE, int port = -1);
+bool AddLocal(const CNetAddr& addr, int nScore = LOCAL_NONE);
bool SeenLocal(const CService& addr);
bool IsLocal(const CService& addr);
bool GetLocal(CService &addr, const CNetAddr *paddrPeer = NULL);
diff --git a/src/netbase.cpp b/src/netbase.cpp
index ebf823e899..2131bdf75b 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -11,6 +11,7 @@
#endif
#include "strlcpy.h"
+#include <boost/algorithm/string/case_conv.hpp> // for to_lower()
using namespace std;
@@ -27,6 +28,7 @@ static bool vfNoProxy[NET_MAX] = {};
static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
enum Network ParseNetwork(std::string net) {
+ boost::to_lower(net);
if (net == "ipv4") return NET_IPV4;
if (net == "ipv6") return NET_IPV6;
if (net == "tor") return NET_TOR;
@@ -464,12 +466,14 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest
int port = portDefault;
size_t colon = strDest.find_last_of(':');
- char *endp = NULL;
- int n = strtol(pszDest + colon + 1, &endp, 10);
- if (endp && *endp == 0 && n >= 0) {
- strDest = strDest.substr(0, colon);
- if (n > 0 && n < 0x10000)
- port = n;
+ if (colon != strDest.npos) {
+ char *endp = NULL;
+ int n = strtol(pszDest + colon + 1, &endp, 10);
+ if (endp && *endp == 0 && n >= 0) {
+ strDest = strDest.substr(0, colon);
+ if (n > 0 && n < 0x10000)
+ port = n;
+ }
}
if (strDest[0] == '[' && strDest[strDest.size()-1] == ']')
strDest = strDest.substr(1, strDest.size()-2);
diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui
index e8f01ff2f5..cded274792 100644
--- a/src/qt/forms/rpcconsole.ui
+++ b/src/qt/forms/rpcconsole.ui
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>706</width>
- <height>382</height>
+ <height>446</height>
</rect>
</property>
<property name="windowTitle">
@@ -327,30 +327,22 @@
<number>3</number>
</property>
<item>
- <widget class="QTableWidget" name="messagesWidget">
+ <widget class="QTextEdit" name="messagesWidget">
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
- <property name="tabKeyNavigation">
- <bool>false</bool>
+ <property name="readOnly">
+ <bool>true</bool>
</property>
- <property name="selectionBehavior">
- <enum>QAbstractItemView::SelectRows</enum>
+ <property name="tabKeyNavigation" stdset="0">
+ <bool>false</bool>
</property>
- <property name="columnCount">
+ <property name="columnCount" stdset="0">
<number>2</number>
</property>
- <attribute name="horizontalHeaderVisible">
- <bool>false</bool>
- </attribute>
- <attribute name="verticalHeaderVisible">
- <bool>false</bool>
- </attribute>
- <column/>
- <column/>
</widget>
</item>
<item>
diff --git a/src/qt/forms/transactiondescdialog.ui b/src/qt/forms/transactiondescdialog.ui
index 9a9f6db158..039cb082cc 100644
--- a/src/qt/forms/transactiondescdialog.ui
+++ b/src/qt/forms/transactiondescdialog.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>400</width>
- <height>300</height>
+ <width>600</width>
+ <height>250</height>
</rect>
</property>
<property name="windowTitle">
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 5a035888ed..33b09952b7 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -10,6 +10,7 @@
#include <QThread>
#include <QTextEdit>
#include <QKeyEvent>
+#include <QUrl>
#include <boost/tokenizer.hpp>
@@ -19,6 +20,19 @@
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
@@ -41,19 +55,26 @@ void RPCExecutor::start()
void RPCExecutor::request(const QString &command)
{
// Parse shell-like command line into separate arguments
- boost::escaped_list_separator<char> els('\\',' ','\"');
- std::string strCommand = command.toStdString();
- boost::tokenizer<boost::escaped_list_separator<char> > tok(strCommand, els);
-
std::string strMethod;
std::vector<std::string> strParams;
- int n = 0;
- for(boost::tokenizer<boost::escaped_list_separator<char> >::iterator beg=tok.begin(); beg!=tok.end();++beg,++n)
+ 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)
{
- if(n == 0) // First parameter is the command
- strMethod = *beg;
- else
- strParams.push_back(*beg);
+ emit reply(RPCConsole::CMD_ERROR, QString("Parse error"));
+ return;
}
try {
@@ -83,12 +104,9 @@ void RPCExecutor::request(const QString &command)
RPCConsole::RPCConsole(QWidget *parent) :
QDialog(parent),
ui(new Ui::RPCConsole),
- firstLayout(true),
historyPtr(0)
{
ui->setupUi(this);
- ui->messagesWidget->horizontalHeader()->setResizeMode(1, QHeaderView::Stretch);
- ui->messagesWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
#ifndef WIN32
// Show Debug logfile label and Open button only for Windows
@@ -99,13 +117,6 @@ RPCConsole::RPCConsole(QWidget *parent) :
// Install event filter for up and down arrow
ui->lineEdit->installEventFilter(this);
- // Add "Copy message" to context menu explicitly
- QAction *copyMessageAction = new QAction(tr("&Copy"), this);
- copyMessageAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_C));
- copyMessageAction->setShortcutContext(Qt::WidgetShortcut);
- connect(copyMessageAction, SIGNAL(triggered()), this, SLOT(copyMessage()));
- ui->messagesWidget->addAction(copyMessageAction);
-
connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
connect(ui->openDebugLogfileButton, SIGNAL(clicked()), this, SLOT(on_openDebugLogfileButton_clicked()));
@@ -159,68 +170,62 @@ void RPCConsole::setClientModel(ClientModel *model)
}
}
-static QColor categoryColor(int category)
+static QString categoryClass(int category)
{
switch(category)
{
- case RPCConsole::MC_ERROR: return QColor(255,0,0); break;
- case RPCConsole::MC_DEBUG: return QColor(192,192,192); break;
- case RPCConsole::CMD_REQUEST: return QColor(128,128,128); break;
- case RPCConsole::CMD_REPLY: return QColor(128,255,128); break;
- case RPCConsole::CMD_ERROR: return QColor(255,128,128); break;
- default: return QColor(0,0,0);
+ 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->messagesWidget->setRowCount(0);
ui->lineEdit->clear();
ui->lineEdit->setFocus();
- message(CMD_REPLY, tr("Welcome to the bitcoin RPC console.")+"\n"+
- tr("Use up and down arrows to navigate history, and Ctrl-L to clear screen.")+"\n"+
- tr("Type \"help\" for an overview of available commands."));
+ // 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>"
+ "Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen.<br>"
+ "Type <b>help</b> for an overview of available commands."), true);
}
-void RPCConsole::message(int category, const QString &message)
+void RPCConsole::message(int category, const QString &message, bool html)
{
- // Add row to messages widget
- int row = ui->messagesWidget->rowCount();
- ui->messagesWidget->setRowCount(row+1);
-
QTime time = QTime::currentTime();
- QTableWidgetItem *newTime = new QTableWidgetItem(time.toString());
- newTime->setData(Qt::DecorationRole, categoryColor(category));
- newTime->setForeground(QColor(128,128,128));
- newTime->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); // make non-editable
-
- int numLines = message.count("\n") + 1;
- // As Qt doesn't like very tall cells (they break scrolling) keep only short messages in
- // the cell text, longer messages trigger a display widget with scroll bar
- if(numLines < 5)
- {
- QTableWidgetItem *newItem = new QTableWidgetItem(message);
- newItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); // make non-editable
- if(category == CMD_ERROR) // Coloring error messages in red
- newItem->setForeground(QColor(255,16,16));
- ui->messagesWidget->setItem(row, 1, newItem);
- } else {
- QTextEdit *newWidget = new QTextEdit;
- newWidget->setText(message);
- newWidget->setMaximumHeight(100);
- newWidget->setReadOnly(true);
- ui->messagesWidget->setCellWidget(row, 1, newWidget);
- }
-
- ui->messagesWidget->setItem(row, 0, newTime);
- ui->messagesWidget->resizeRowToContents(row);
- // Preserve only limited scrollback buffer
- while(ui->messagesWidget->rowCount() > CONSOLE_SCROLLBACK)
- ui->messagesWidget->removeRow(0);
- // Scroll to bottom after table is updated
- QTimer::singleShot(0, ui->messagesWidget, SLOT(scrollToBottom()));
+ 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)
@@ -298,24 +303,10 @@ void RPCConsole::startExecutor()
thread->start();
}
-void RPCConsole::copyMessage()
-{
- GUIUtil::copyEntryData(ui->messagesWidget, 1, Qt::EditRole);
-}
-
void RPCConsole::on_tabWidget_currentChanged(int index)
{
if(ui->tabWidget->widget(index) == ui->tab_console)
{
- if(firstLayout)
- {
- // Work around QTableWidget issue:
- // Call resizeRowsToContents on first Layout request with widget visible,
- // to make sure multiline messages that were added before the console was shown
- // have the right height.
- firstLayout = false;
- ui->messagesWidget->resizeRowsToContents();
- }
ui->lineEdit->setFocus();
}
}
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index 30948eaad2..9c4fab497e 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -37,15 +37,13 @@ private slots:
public slots:
void clear();
- void message(int category, const QString &message);
+ void message(int category, const QString &message, bool html = false);
/** Set number of connections shown in the UI */
void setNumConnections(int count);
/** Set number of blocks shown in the UI */
void setNumBlocks(int count);
/** Go forward or back in history */
void browseHistory(int offset);
- /** Copy currently selected message to clipboard */
- void copyMessage();
signals:
// For RPC command executor
@@ -55,7 +53,6 @@ signals:
private:
Ui::RPCConsole *ui;
ClientModel *clientModel;
- bool firstLayout;
QStringList history;
int historyPtr;