Browse Source

Merge pull request #4285

a5b2d9c [Qt] tweak new peers tab in console window (Philip Kaufmann)
0.10
Wladimir J. van der Laan 11 years ago
parent
commit
1913302fb7
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
  1. 364
      src/qt/forms/rpcconsole.ui
  2. 5
      src/qt/guiutil.cpp
  3. 3
      src/qt/guiutil.h
  4. 64
      src/qt/peertablemodel.cpp
  5. 9
      src/qt/peertablemodel.h
  6. 155
      src/qt/rpcconsole.cpp
  7. 29
      src/qt/rpcconsole.h

364
src/qt/forms/rpcconsole.ui

@ -428,7 +428,7 @@ @@ -428,7 +428,7 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tab">
<widget class="QWidget" name="tab_nettraffic">
<attribute name="title">
<string>&amp;Network Traffic</string>
</attribute>
@ -683,6 +683,19 @@ @@ -683,6 +683,19 @@
<string>&amp;Peers</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0" rowspan="2">
<widget class="QTableView" name="peerWidget">
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<attribute name="horizontalHeaderHighlightSections">
<bool>false</bool>
</attribute>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="peerHeading">
<property name="sizePolicy">
@ -691,262 +704,377 @@ @@ -691,262 +704,377 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Select a peer to view detailed information.</string>
<property name="minimumSize">
<size>
<width>300</width>
<height>32</height>
</size>
</property>
<property name="margin">
<number>3</number>
<property name="font">
<font>
<pointsize>10</pointsize>
</font>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="2">
<widget class="QTableView" name="peerWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
<property name="text">
<string>Select a peer to view detailed information.</string>
</property>
<property name="editTriggers">
<set>QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed</set>
<property name="alignment">
<set>Qt::AlignHCenter|Qt::AlignTop</set>
</property>
<property name="sortingEnabled">
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QWidget" name="detailWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<property name="minimumSize">
<size>
<width>300</width>
<height>0</height>
</size>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="leftMargin">
<number>3</number>
</property>
<item row="12" column="0">
<widget class="QLabel" name="label_21">
<item row="0" column="0">
<widget class="QLabel" name="label_23">
<property name="text">
<string>Version:</string>
<string>Direction</string>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QLabel" name="peerPingTime">
<item row="0" column="2">
<widget class="QLabel" name="peerDirection">
<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">
<widget class="QLabel" name="label_19">
<item row="1" column="0">
<widget class="QLabel" name="label_21">
<property name="text">
<string>Last Receive:</string>
<string>Version</string>
</property>
</widget>
</item>
<item row="14" column="0">
<widget class="QLabel" name="label_28">
<item row="1" column="2">
<widget class="QLabel" name="peerVersion">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
<string>User Agent:</string>
<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="1">
<widget class="QLabel" name="peerVersion">
<item row="2" column="0">
<widget class="QLabel" name="label_28">
<property name="text">
<string>N/A</string>
<string>User Agent</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLabel" name="peerConnTime">
<property name="minimumSize">
<size>
<width>160</width>
<height>0</height>
</size>
<item row="2" column="2">
<widget class="QLabel" name="peerSubversion">
<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">
<widget class="QLabel" name="label_26">
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Ping Time:</string>
<string>Services</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="peerLastRecv">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<item row="3" column="2">
<widget class="QLabel" name="peerServices">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
<string>N/A</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_22">
<property name="text">
<string>Connection Time:</string>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="peerBytesSent">
<item row="4" column="0">
<widget class="QLabel" name="label_25">
<property name="text">
<string>N/A</string>
<string>Sync Node</string>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QLabel" name="peerSubversion">
<item row="4" column="2">
<widget class="QLabel" name="peerSyncNode">
<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="15" column="0">
<item row="5" column="0">
<widget class="QLabel" name="label_29">
<property name="text">
<string>Starting Height:</string>
<string>Starting Height</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLabel" name="peerBytesRecv">
<item row="5" column="2">
<widget class="QLabel" name="peerHeight">
<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="6" column="0">
<widget class="QLabel" name="label_18">
<widget class="QLabel" name="label_27">
<property name="text">
<string>Bytes Sent:</string>
<string>Sync Height</string>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QLabel" name="peerSyncHeight">
<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">
<widget class="QLabel" name="label_20">
<widget class="QLabel" name="label_24">
<property name="text">
<string>Bytes Received:</string>
<string>Ban Score</string>
</property>
</widget>
</item>
<item row="15" column="1">
<widget class="QLabel" name="peerHeight">
<item row="7" column="2">
<widget class="QLabel" name="peerBanScore">
<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="16" column="0">
<widget class="QLabel" name="label_24">
<item row="8" column="0">
<widget class="QLabel" name="label_22">
<property name="text">
<string>Ban Score:</string>
<string>Connection Time</string>
</property>
</widget>
</item>
<item row="16" column="1">
<widget class="QLabel" name="peerBanScore">
<item row="8" column="2">
<widget class="QLabel" name="peerConnTime">
<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="17" column="0">
<widget class="QLabel" name="label_23">
<item row="9" column="0">
<widget class="QLabel" name="label_15">
<property name="text">
<string>Direction:</string>
<string>Last Send</string>
</property>
</widget>
</item>
<item row="17" column="1">
<widget class="QLabel" name="peerDirection">
<item row="9" column="2">
<widget class="QLabel" name="peerLastSend">
<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="19" column="0">
<widget class="QLabel" name="label_25">
<item row="10" column="0">
<widget class="QLabel" name="label_19">
<property name="text">
<string>Sync Node:</string>
<string>Last Receive</string>
</property>
</widget>
</item>
<item row="19" column="1">
<widget class="QLabel" name="peerSyncNode">
<item row="10" column="2">
<widget class="QLabel" name="peerLastRecv">
<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_15">
<item row="11" column="0">
<widget class="QLabel" name="label_18">
<property name="text">
<string>Last Send:</string>
<string>Bytes Sent</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<item row="11" column="2">
<widget class="QLabel" name="peerBytesSent">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
<string>Services:</string>
<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="1" column="0">
<widget class="QLabel" name="label_27">
<item row="12" column="0">
<widget class="QLabel" name="label_20">
<property name="text">
<string>IP Address/port:</string>
<string>Bytes Received</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="peerLastSend">
<item row="12" column="2">
<widget class="QLabel" name="peerBytesRecv">
<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="1">
<widget class="QLabel" name="peerServices">
<item row="13" column="0">
<widget class="QLabel" name="label_26">
<property name="text">
<string>N/A</string>
<string>Ping Time</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="peerAddr">
<item row="13" column="2">
<widget class="QLabel" name="peerPingTime">
<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="20" column="0">
<widget class="QWidget" name="widget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<item row="14" column="1">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>

5
src/qt/guiutil.cpp

@ -804,4 +804,9 @@ QString formatServicesStr(uint64_t mask) @@ -804,4 +804,9 @@ QString formatServicesStr(uint64_t mask)
return QObject::tr("None");
}
QString formatPingTime(double dPingTime)
{
return dPingTime == 0 ? QObject::tr("N/A") : QString(QObject::tr("%1 s")).arg(QString::number(dPingTime, 'f', 3));
}
} // namespace GUIUtil

3
src/qt/guiutil.h

@ -178,6 +178,9 @@ namespace GUIUtil @@ -178,6 +178,9 @@ namespace GUIUtil
/* Format CNodeStats.nServices bitmask into a user-readable string */
QString formatServicesStr(uint64_t mask);
/* Format a CNodeCombinedStats.dPingTime into a user-readable string or display N/A, if 0*/
QString formatPingTime(double dPingTime);
} // namespace GUIUtil
#endif // GUIUTIL_H

64
src/qt/peertablemodel.cpp

@ -5,6 +5,8 @@ @@ -5,6 +5,8 @@
#include "peertablemodel.h"
#include "clientmodel.h"
#include "guiconstants.h"
#include "guiutil.h"
#include "net.h"
#include "sync.h"
@ -15,8 +17,8 @@ @@ -15,8 +17,8 @@
bool NodeLessThan::operator()(const CNodeCombinedStats &left, const CNodeCombinedStats &right) const
{
const CNodeStats *pLeft = &(left.nodestats);
const CNodeStats *pRight = &(right.nodestats);
const CNodeStats *pLeft = &(left.nodeStats);
const CNodeStats *pRight = &(right.nodeStats);
if (order == Qt::DescendingOrder)
std::swap(pLeft, pRight);
@ -27,8 +29,8 @@ bool NodeLessThan::operator()(const CNodeCombinedStats &left, const CNodeCombine @@ -27,8 +29,8 @@ bool NodeLessThan::operator()(const CNodeCombinedStats &left, const CNodeCombine
return pLeft->addrName.compare(pRight->addrName) < 0;
case PeerTableModel::Subversion:
return pLeft->cleanSubVer.compare(pRight->cleanSubVer) < 0;
case PeerTableModel::Height:
return pLeft->nStartingHeight < pRight->nStartingHeight;
case PeerTableModel::Ping:
return pLeft->dPingTime < pRight->dPingTime;
}
return false;
@ -48,7 +50,8 @@ public: @@ -48,7 +50,8 @@ public:
std::map<NodeId, int> mapNodeRows;
/** Pull a full list of peers from vNodes into our cache */
void refreshPeers() {
void refreshPeers()
{
{
TRY_LOCK(cs_vNodes, lockNodes);
if (!lockNodes)
@ -63,23 +66,17 @@ public: @@ -63,23 +66,17 @@ public:
BOOST_FOREACH(CNode* pnode, vNodes)
{
CNodeCombinedStats stats;
stats.statestats.nMisbehavior = -1;
pnode->copyStats(stats.nodestats);
stats.nodeStateStats.nMisbehavior = 0;
stats.nodeStateStats.nSyncHeight = -1;
stats.fNodeStateStatsAvailable = false;
pnode->copyStats(stats.nodeStats);
cachedNodeStats.append(stats);
}
}
// if we can, retrieve the CNodeStateStats for each node.
{
TRY_LOCK(cs_main, lockMain);
if (lockMain)
{
BOOST_FOREACH(CNodeCombinedStats &stats, cachedNodeStats)
{
GetNodeStateStats(stats.nodestats.nodeid, stats.statestats);
}
}
}
// Try to retrieve the CNodeStateStats for each node.
BOOST_FOREACH(CNodeCombinedStats &stats, cachedNodeStats)
stats.fNodeStateStatsAvailable = GetNodeStateStats(stats.nodeStats.nodeid, stats.nodeStateStats);
if (sortColumn >= 0)
// sort cacheNodeStats (use stable sort to prevent rows jumping around unneceesarily)
@ -89,9 +86,7 @@ public: @@ -89,9 +86,7 @@ public:
mapNodeRows.clear();
int row = 0;
BOOST_FOREACH(CNodeCombinedStats &stats, cachedNodeStats)
{
mapNodeRows.insert(std::pair<NodeId, int>(stats.nodestats.nodeid, row++));
}
mapNodeRows.insert(std::pair<NodeId, int>(stats.nodeStats.nodeid, row++));
}
int size()
@ -103,18 +98,18 @@ public: @@ -103,18 +98,18 @@ public:
{
if(idx >= 0 && idx < cachedNodeStats.size()) {
return &cachedNodeStats[idx];
}
else
{
} else {
return 0;
}
}
};
PeerTableModel::PeerTableModel(ClientModel *parent) :
QAbstractTableModel(parent),clientModel(parent),timer(0)
QAbstractTableModel(parent),
clientModel(parent),
timer(0)
{
columns << tr("Address") << tr("User Agent") << tr("Start Height");
columns << tr("Address/Hostname") << tr("User Agent") << tr("Ping Time");
priv = new PeerTablePriv();
// default to unsorted
priv->sortColumn = -1;
@ -122,14 +117,14 @@ PeerTableModel::PeerTableModel(ClientModel *parent) : @@ -122,14 +117,14 @@ PeerTableModel::PeerTableModel(ClientModel *parent) :
// set up timer for auto refresh
timer = new QTimer();
connect(timer, SIGNAL(timeout()), SLOT(refresh()));
timer->setInterval(MODEL_UPDATE_DELAY);
// load initial data
refresh();
}
void PeerTableModel::startAutoRefresh(int msecs)
void PeerTableModel::startAutoRefresh()
{
timer->setInterval(1000);
timer->start();
}
@ -147,7 +142,7 @@ int PeerTableModel::rowCount(const QModelIndex &parent) const @@ -147,7 +142,7 @@ int PeerTableModel::rowCount(const QModelIndex &parent) const
int PeerTableModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return 3;
return columns.length();;
}
QVariant PeerTableModel::data(const QModelIndex &index, int role) const
@ -162,11 +157,11 @@ QVariant PeerTableModel::data(const QModelIndex &index, int role) const @@ -162,11 +157,11 @@ QVariant PeerTableModel::data(const QModelIndex &index, int role) const
switch(index.column())
{
case Address:
return QVariant(rec->nodestats.addrName.c_str());
return QString::fromStdString(rec->nodeStats.addrName);
case Subversion:
return QVariant(rec->nodestats.cleanSubVer.c_str());
case Height:
return rec->nodestats.nStartingHeight;
return QString::fromStdString(rec->nodeStats.cleanSubVer);
case Ping:
return GUIUtil::formatPingTime(rec->nodeStats.dPingTime);
}
}
return QVariant();
@ -208,7 +203,8 @@ QModelIndex PeerTableModel::index(int row, int column, const QModelIndex &parent @@ -208,7 +203,8 @@ QModelIndex PeerTableModel::index(int row, int column, const QModelIndex &parent
}
}
const CNodeCombinedStats *PeerTableModel::getNodeStats(int idx) {
const CNodeCombinedStats *PeerTableModel::getNodeStats(int idx)
{
return priv->index(idx);
}

9
src/qt/peertablemodel.h

@ -19,8 +19,9 @@ class QTimer; @@ -19,8 +19,9 @@ class QTimer;
QT_END_NAMESPACE
struct CNodeCombinedStats {
CNodeStats nodestats;
CNodeStateStats statestats;
CNodeStats nodeStats;
CNodeStateStats nodeStateStats;
bool fNodeStateStatsAvailable;
};
class NodeLessThan
@ -47,13 +48,13 @@ public: @@ -47,13 +48,13 @@ public:
explicit PeerTableModel(ClientModel *parent = 0);
const CNodeCombinedStats *getNodeStats(int idx);
int getRowByNodeId(NodeId nodeid);
void startAutoRefresh(int msecs);
void startAutoRefresh();
void stopAutoRefresh();
enum ColumnIndex {
Address = 0,
Subversion = 1,
Height = 2
Ping = 2
};
/** @name Methods overridden from QAbstractTableModel

155
src/qt/rpcconsole.cpp

@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
#include "peertablemodel.h"
#include "main.h"
#include "chainparams.h"
#include "rpcserver.h"
#include "rpcclient.h"
#include "util.h"
@ -200,12 +201,9 @@ RPCConsole::RPCConsole(QWidget *parent) : @@ -200,12 +201,9 @@ RPCConsole::RPCConsole(QWidget *parent) :
QDialog(parent),
ui(new Ui::RPCConsole),
clientModel(0),
historyPtr(0)
historyPtr(0),
cachedNodeid(-1)
{
detailNodeStats = CNodeCombinedStats();
detailNodeStats.nodestats.nodeid = -1;
detailNodeStats.statestats.nMisbehavior = -1;
ui->setupUi(this);
GUIUtil::restoreWindowGeometry("nRPCConsoleWindow", this->size(), this);
@ -233,6 +231,7 @@ RPCConsole::RPCConsole(QWidget *parent) : @@ -233,6 +231,7 @@ RPCConsole::RPCConsole(QWidget *parent) :
setTrafficGraphRange(INITIAL_TRAFFIC_GRAPH_MINS);
ui->detailWidget->hide();
ui->peerHeading->setText(tr("Select a peer to view detailed information."));
clear();
}
@ -303,11 +302,11 @@ void RPCConsole::setClientModel(ClientModel *model) @@ -303,11 +302,11 @@ void RPCConsole::setClientModel(ClientModel *model)
ui->peerWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->peerWidget->setSelectionMode(QAbstractItemView::SingleSelection);
ui->peerWidget->setColumnWidth(PeerTableModel::Address, ADDRESS_COLUMN_WIDTH);
columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(ui->peerWidget, MINIMUM_COLUMN_WIDTH, MINIMUM_COLUMN_WIDTH);
ui->peerWidget->setColumnWidth(PeerTableModel::Subversion, SUBVERSION_COLUMN_WIDTH);
ui->peerWidget->setColumnWidth(PeerTableModel::Ping, PING_COLUMN_WIDTH);
// connect the peerWidget's selection model to our peerSelected() handler
QItemSelectionModel *peerSelectModel = ui->peerWidget->selectionModel();
connect(peerSelectModel, SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
// connect the peerWidget selection model to our peerSelected() handler
connect(ui->peerWidget->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
this, SLOT(peerSelected(const QItemSelection &, const QItemSelection &)));
connect(model->getPeerTableModel(), SIGNAL(layoutChanged()), this, SLOT(peerLayoutChanged()));
@ -473,10 +472,6 @@ void RPCConsole::on_tabWidget_currentChanged(int index) @@ -473,10 +472,6 @@ void RPCConsole::on_tabWidget_currentChanged(int index)
{
ui->lineEdit->setFocus();
}
else if(ui->tabWidget->widget(index) == ui->tab_peers)
{
initPeerTable();
}
}
void RPCConsole::on_openDebugLogfileButton_clicked()
@ -525,30 +520,24 @@ void RPCConsole::peerSelected(const QItemSelection &selected, const QItemSelecti @@ -525,30 +520,24 @@ void RPCConsole::peerSelected(const QItemSelection &selected, const QItemSelecti
{
Q_UNUSED(deselected);
if (selected.indexes().isEmpty())
if (!clientModel || selected.indexes().isEmpty())
return;
// mark the cached banscore as unknown
detailNodeStats.statestats.nMisbehavior = -1;
const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(selected.indexes().first().row());
if (stats)
{
detailNodeStats.nodestats.nodeid = stats->nodestats.nodeid;
updateNodeDetail(stats);
ui->detailWidget->show();
ui->detailWidget->setDisabled(false);
}
}
void RPCConsole::peerLayoutChanged()
{
if (!clientModel)
return;
const CNodeCombinedStats *stats = NULL;
bool fUnselect = false, fReselect = false, fDisconnected = false;
bool fUnselect = false;
bool fReselect = false;
if (detailNodeStats.nodestats.nodeid == -1)
// no node selected yet
if (cachedNodeid == -1) // no node selected yet
return;
// find the currently selected row
@ -561,14 +550,15 @@ void RPCConsole::peerLayoutChanged() @@ -561,14 +550,15 @@ void RPCConsole::peerLayoutChanged()
// check if our detail node has a row in the table (it may not necessarily
// be at selectedRow since its position can change after a layout change)
int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(detailNodeStats.nodestats.nodeid);
int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(cachedNodeid);
if (detailNodeRow < 0)
{
// detail node dissapeared from table (node disconnected)
fUnselect = true;
fDisconnected = true;
detailNodeStats.nodestats.nodeid = 0;
cachedNodeid = -1;
ui->detailWidget->hide();
ui->peerHeading->setText(tr("Select a peer to view detailed information."));
}
else
{
@ -596,91 +586,64 @@ void RPCConsole::peerLayoutChanged() @@ -596,91 +586,64 @@ void RPCConsole::peerLayoutChanged()
if (stats)
updateNodeDetail(stats);
if (fDisconnected)
{
ui->peerHeading->setText(QString(tr("Peer Disconnected")));
ui->detailWidget->setDisabled(true);
QDateTime dt = QDateTime::fromTime_t(detailNodeStats.nodestats.nLastSend);
if (detailNodeStats.nodestats.nLastSend)
ui->peerLastSend->setText(dt.toString("yyyy-MM-dd hh:mm:ss"));
dt.setTime_t(detailNodeStats.nodestats.nLastRecv);
if (detailNodeStats.nodestats.nLastRecv)
ui->peerLastRecv->setText(dt.toString("yyyy-MM-dd hh:mm:ss"));
dt.setTime_t(detailNodeStats.nodestats.nTimeConnected);
ui->peerConnTime->setText(dt.toString("yyyy-MM-dd hh:mm:ss"));
}
}
void RPCConsole::updateNodeDetail(const CNodeCombinedStats *combinedStats)
void RPCConsole::updateNodeDetail(const CNodeCombinedStats *stats)
{
CNodeStats stats = combinedStats->nodestats;
// keep a copy of timestamps, used to display dates upon disconnect
detailNodeStats.nodestats.nLastSend = stats.nLastSend;
detailNodeStats.nodestats.nLastRecv = stats.nLastRecv;
detailNodeStats.nodestats.nTimeConnected = stats.nTimeConnected;
// Update cached nodeid
cachedNodeid = stats->nodeStats.nodeid;
// update the detail ui with latest node information
ui->peerHeading->setText(QString("<b>%1</b>").arg(tr("Node Detail")));
ui->peerAddr->setText(QString(stats.addrName.c_str()));
ui->peerServices->setText(GUIUtil::formatServicesStr(stats.nServices));
ui->peerLastSend->setText(stats.nLastSend ? GUIUtil::formatDurationStr(GetTime() - stats.nLastSend) : tr("never"));
ui->peerLastRecv->setText(stats.nLastRecv ? GUIUtil::formatDurationStr(GetTime() - stats.nLastRecv) : tr("never"));
ui->peerBytesSent->setText(FormatBytes(stats.nSendBytes));
ui->peerBytesRecv->setText(FormatBytes(stats.nRecvBytes));
ui->peerConnTime->setText(GUIUtil::formatDurationStr(GetTime() - stats.nTimeConnected));
ui->peerPingTime->setText(stats.dPingTime == 0 ? tr("N/A") : QString(tr("%1 secs")).arg(QString::number(stats.dPingTime, 'f', 3)));
ui->peerVersion->setText(QString("%1").arg(stats.nVersion));
ui->peerSubversion->setText(QString(stats.cleanSubVer.c_str()));
ui->peerDirection->setText(stats.fInbound ? tr("Inbound") : tr("Outbound"));
ui->peerHeight->setText(QString("%1").arg(stats.nStartingHeight));
ui->peerSyncNode->setText(stats.fSyncNode ? tr("Yes") : tr("No"));
// if we can, display the peer's ban score
CNodeStateStats statestats = combinedStats->statestats;
if (statestats.nMisbehavior >= 0)
{
// we have a new nMisbehavor value - update the cache
detailNodeStats.statestats.nMisbehavior = statestats.nMisbehavior;
}
// pull the ban score from cache. -1 means it hasn't been retrieved yet (lock busy).
if (detailNodeStats.statestats.nMisbehavior >= 0)
ui->peerBanScore->setText(QString("%1").arg(detailNodeStats.statestats.nMisbehavior));
else
QString peerAddrDetails(QString::fromStdString(stats->nodeStats.addrName));
if (!stats->nodeStats.addrLocal.empty())
peerAddrDetails += "<br />" + tr("via %1").arg(QString::fromStdString(stats->nodeStats.addrLocal));
ui->peerHeading->setText(peerAddrDetails);
ui->peerServices->setText(GUIUtil::formatServicesStr(stats->nodeStats.nServices));
ui->peerLastSend->setText(stats->nodeStats.nLastSend ? GUIUtil::formatDurationStr(GetTime() - stats->nodeStats.nLastSend) : tr("never"));
ui->peerLastRecv->setText(stats->nodeStats.nLastRecv ? GUIUtil::formatDurationStr(GetTime() - stats->nodeStats.nLastRecv) : tr("never"));
ui->peerBytesSent->setText(FormatBytes(stats->nodeStats.nSendBytes));
ui->peerBytesRecv->setText(FormatBytes(stats->nodeStats.nRecvBytes));
ui->peerConnTime->setText(GUIUtil::formatDurationStr(GetTime() - stats->nodeStats.nTimeConnected));
ui->peerPingTime->setText(GUIUtil::formatPingTime(stats->nodeStats.dPingTime));
ui->peerVersion->setText(QString("%1").arg(stats->nodeStats.nVersion));
ui->peerSubversion->setText(QString::fromStdString(stats->nodeStats.cleanSubVer));
ui->peerDirection->setText(stats->nodeStats.fInbound ? tr("Inbound") : tr("Outbound"));
ui->peerHeight->setText(QString("%1").arg(stats->nodeStats.nStartingHeight));
ui->peerSyncNode->setText(stats->nodeStats.fSyncNode ? tr("Yes") : tr("No"));
// This check fails for example if the lock was busy and
// nodeStateStats couldn't be fetched.
if (stats->fNodeStateStatsAvailable) {
// Ban score is init to 0
ui->peerBanScore->setText(QString("%1").arg(stats->nodeStateStats.nMisbehavior));
// Sync height is init to -1
if (stats->nodeStateStats.nSyncHeight > -1)
ui->peerSyncHeight->setText(QString("%1").arg(stats->nodeStateStats.nSyncHeight));
else
ui->peerSyncHeight->setText(tr("Unknown"));
} else {
ui->peerBanScore->setText(tr("Fetching..."));
}
void RPCConsole::initPeerTable()
{
if (!clientModel)
return;
// peerWidget needs a resize in case the dialog has non-default geometry
columnResizingFixer->stretchColumnWidth(PeerTableModel::Address);
ui->peerSyncHeight->setText(tr("Fetching..."));
}
// start PeerTableModel auto refresh
clientModel->getPeerTableModel()->startAutoRefresh(1000);
ui->detailWidget->show();
}
// We override the virtual resizeEvent of the QWidget to adjust tables column
// sizes as the tables width is proportional to the dialogs width.
void RPCConsole::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
if (!clientModel)
return;
columnResizingFixer->stretchColumnWidth(PeerTableModel::Address);
}
void RPCConsole::showEvent(QShowEvent *event)
{
QWidget::showEvent(event);
initPeerTable();
if (!clientModel)
return;
// start PeerTableModel auto refresh
clientModel->getPeerTableModel()->startAutoRefresh();
}
void RPCConsole::hideEvent(QHideEvent *event)

29
src/qt/rpcconsole.h

@ -44,21 +44,6 @@ public: @@ -44,21 +44,6 @@ public:
protected:
virtual bool eventFilter(QObject* obj, QEvent *event);
private:
/** show detailed information on ui about selected node */
void updateNodeDetail(const CNodeCombinedStats *combinedStats);
/** initialize peer table */
void initPeerTable();
enum ColumnWidths
{
ADDRESS_COLUMN_WIDTH = 250,
MINIMUM_COLUMN_WIDTH = 120
};
/** track the node that we are currently viewing detail on in the peers tab */
CNodeCombinedStats detailNodeStats;
private slots:
void on_lineEdit_returnPressed();
void on_tabWidget_currentChanged(int index);
@ -96,15 +81,23 @@ signals: @@ -96,15 +81,23 @@ signals:
private:
static QString FormatBytes(quint64 bytes);
void startExecutor();
void setTrafficGraphRange(int mins);
/** show detailed information on ui about selected node */
void updateNodeDetail(const CNodeCombinedStats *stats);
enum ColumnWidths
{
ADDRESS_COLUMN_WIDTH = 200,
SUBVERSION_COLUMN_WIDTH = 100,
PING_COLUMN_WIDTH = 80
};
Ui::RPCConsole *ui;
ClientModel *clientModel;
QStringList history;
GUIUtil::TableViewLastColumnResizingFixer *columnResizingFixer;
int historyPtr;
void startExecutor();
NodeId cachedNodeid;
};
#endif // RPCCONSOLE_H

Loading…
Cancel
Save