diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2014-08-04 16:09:18 +0200 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2014-08-04 16:11:29 +0200 |
commit | 1913302fb7b1659feb72f3a532f5c5be0e8391e3 (patch) | |
tree | f8ede7b943a1769a989f146e1f72ce1d6c55e3ab | |
parent | d97a58f883c57da0507dde6dce9b8431f88e739c (diff) | |
parent | a5b2d9c82e985fa8df4457072b4fa30781f1d53a (diff) |
Merge pull request #4285
a5b2d9c [Qt] tweak new peers tab in console window (Philip Kaufmann)
-rw-r--r-- | src/qt/forms/rpcconsole.ui | 364 | ||||
-rw-r--r-- | src/qt/guiutil.cpp | 5 | ||||
-rw-r--r-- | src/qt/guiutil.h | 3 | ||||
-rw-r--r-- | src/qt/peertablemodel.cpp | 64 | ||||
-rw-r--r-- | src/qt/peertablemodel.h | 9 | ||||
-rw-r--r-- | src/qt/rpcconsole.cpp | 155 | ||||
-rw-r--r-- | src/qt/rpcconsole.h | 29 |
7 files changed, 359 insertions, 270 deletions
diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui index 7158b65c2d..b9b90aa846 100644 --- a/src/qt/forms/rpcconsole.ui +++ b/src/qt/forms/rpcconsole.ui @@ -428,7 +428,7 @@ </item> </layout> </widget> - <widget class="QWidget" name="tab"> + <widget class="QWidget" name="tab_nettraffic"> <attribute name="title"> <string>&Network Traffic</string> </attribute> @@ -683,6 +683,19 @@ <string>&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 @@ <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> diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 33a50a078d..6258c4160c 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -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 diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 45c78b4e14..dd31d051ee 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -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 diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index 981d063c49..4c650bdec9 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -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 @@ 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 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: 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: 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: 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: { 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) : // 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 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 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 } } -const CNodeCombinedStats *PeerTableModel::getNodeStats(int idx) { +const CNodeCombinedStats *PeerTableModel::getNodeStats(int idx) +{ return priv->index(idx); } diff --git a/src/qt/peertablemodel.h b/src/qt/peertablemodel.h index 385bf0e0c1..38f2662f89 100644 --- a/src/qt/peertablemodel.h +++ b/src/qt/peertablemodel.h @@ -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: 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 diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 9b67f8125f..11089b2497 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -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) : 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) : 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) 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) { 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 { 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() // 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() 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) diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 94672b30cc..64bb5c29b3 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -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: 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 |