Bitcoin Core  21.99.0
P2P Digital Currency
peertablemodel.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2020 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <qt/peertablemodel.h>
6 
7 #include <qt/guiconstants.h>
8 #include <qt/guiutil.h>
9 
10 #include <interfaces/node.h>
11 
12 #include <utility>
13 
14 #include <QDebug>
15 #include <QList>
16 #include <QTimer>
17 
18 bool NodeLessThan::operator()(const CNodeCombinedStats &left, const CNodeCombinedStats &right) const
19 {
20  const CNodeStats *pLeft = &(left.nodeStats);
21  const CNodeStats *pRight = &(right.nodeStats);
22 
23  if (order == Qt::DescendingOrder)
24  std::swap(pLeft, pRight);
25 
26  switch (static_cast<PeerTableModel::ColumnIndex>(column)) {
28  return pLeft->nodeid < pRight->nodeid;
30  return pLeft->addrName.compare(pRight->addrName) < 0;
32  return pLeft->m_conn_type < pRight->m_conn_type;
34  return pLeft->m_network < pRight->m_network;
36  return pLeft->m_min_ping_time < pRight->m_min_ping_time;
38  return pLeft->nSendBytes < pRight->nSendBytes;
40  return pLeft->nRecvBytes < pRight->nRecvBytes;
42  return pLeft->cleanSubVer.compare(pRight->cleanSubVer) < 0;
43  } // no default case, so the compiler can warn about missing cases
44  assert(false);
45 }
46 
47 // private implementation
49 {
50 public:
52  QList<CNodeCombinedStats> cachedNodeStats;
54  int sortColumn{-1};
56  Qt::SortOrder sortOrder;
58  std::map<NodeId, int> mapNodeRows;
59 
62  {
63  {
64  cachedNodeStats.clear();
65 
66  interfaces::Node::NodesStats nodes_stats;
67  node.getNodesStats(nodes_stats);
68  cachedNodeStats.reserve(nodes_stats.size());
69  for (const auto& node_stats : nodes_stats)
70  {
71  CNodeCombinedStats stats;
72  stats.nodeStats = std::get<0>(node_stats);
73  stats.fNodeStateStatsAvailable = std::get<1>(node_stats);
74  stats.nodeStateStats = std::get<2>(node_stats);
75  cachedNodeStats.append(stats);
76  }
77  }
78 
79  if (sortColumn >= 0)
80  // sort cacheNodeStats (use stable sort to prevent rows jumping around unnecessarily)
81  std::stable_sort(cachedNodeStats.begin(), cachedNodeStats.end(), NodeLessThan(sortColumn, sortOrder));
82 
83  // build index map
84  mapNodeRows.clear();
85  int row = 0;
86  for (const CNodeCombinedStats& stats : cachedNodeStats)
87  mapNodeRows.insert(std::pair<NodeId, int>(stats.nodeStats.nodeid, row++));
88  }
89 
90  int size() const
91  {
92  return cachedNodeStats.size();
93  }
94 
96  {
97  if (idx >= 0 && idx < cachedNodeStats.size())
98  return &cachedNodeStats[idx];
99 
100  return nullptr;
101  }
102 };
103 
105  QAbstractTableModel(parent),
106  m_node(node),
107  timer(nullptr)
108 {
109  priv.reset(new PeerTablePriv());
110 
111  // set up timer for auto refresh
112  timer = new QTimer(this);
113  connect(timer, &QTimer::timeout, this, &PeerTableModel::refresh);
114  timer->setInterval(MODEL_UPDATE_DELAY);
115 
116  // load initial data
117  refresh();
118 }
119 
121 {
122  // Intentionally left empty
123 }
124 
126 {
127  timer->start();
128 }
129 
131 {
132  timer->stop();
133 }
134 
135 int PeerTableModel::rowCount(const QModelIndex &parent) const
136 {
137  if (parent.isValid()) {
138  return 0;
139  }
140  return priv->size();
141 }
142 
143 int PeerTableModel::columnCount(const QModelIndex &parent) const
144 {
145  if (parent.isValid()) {
146  return 0;
147  }
148  return columns.length();
149 }
150 
151 QVariant PeerTableModel::data(const QModelIndex &index, int role) const
152 {
153  if(!index.isValid())
154  return QVariant();
155 
156  CNodeCombinedStats *rec = static_cast<CNodeCombinedStats*>(index.internalPointer());
157 
158  const auto column = static_cast<ColumnIndex>(index.column());
159  if (role == Qt::DisplayRole) {
160  switch (column) {
161  case NetNodeId:
162  return (qint64)rec->nodeStats.nodeid;
163  case Address:
164  // prepend to peer address down-arrow symbol for inbound connection and up-arrow for outbound connection
165  return QString(rec->nodeStats.fInbound ? "↓ " : "↑ ") + QString::fromStdString(rec->nodeStats.addrName);
166  case ConnectionType:
167  return GUIUtil::ConnectionTypeToQString(rec->nodeStats.m_conn_type, /* prepend_direction */ false);
168  case Network:
170  case Ping:
172  case Sent:
174  case Received:
176  case Subversion:
177  return QString::fromStdString(rec->nodeStats.cleanSubVer);
178  } // no default case, so the compiler can warn about missing cases
179  assert(false);
180  } else if (role == Qt::TextAlignmentRole) {
181  switch (column) {
182  case NetNodeId:
183  case Address:
184  return {};
185  case ConnectionType:
186  case Network:
187  return QVariant(Qt::AlignCenter);
188  case Ping:
189  case Sent:
190  case Received:
191  return QVariant(Qt::AlignRight | Qt::AlignVCenter);
192  case Subversion:
193  return {};
194  } // no default case, so the compiler can warn about missing cases
195  assert(false);
196  } else if (role == StatsRole) {
197  switch (index.column()) {
198  case NetNodeId: return QVariant::fromValue(rec);
199  default: return QVariant();
200  }
201  }
202 
203  return QVariant();
204 }
205 
206 QVariant PeerTableModel::headerData(int section, Qt::Orientation orientation, int role) const
207 {
208  if(orientation == Qt::Horizontal)
209  {
210  if(role == Qt::DisplayRole && section < columns.size())
211  {
212  return columns[section];
213  }
214  }
215  return QVariant();
216 }
217 
218 Qt::ItemFlags PeerTableModel::flags(const QModelIndex &index) const
219 {
220  if (!index.isValid()) return Qt::NoItemFlags;
221 
222  Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
223  return retval;
224 }
225 
226 QModelIndex PeerTableModel::index(int row, int column, const QModelIndex &parent) const
227 {
228  Q_UNUSED(parent);
229  CNodeCombinedStats *data = priv->index(row);
230 
231  if (data)
232  return createIndex(row, column, data);
233  return QModelIndex();
234 }
235 
237 {
238  Q_EMIT layoutAboutToBeChanged();
239  priv->refreshPeers(m_node);
240  Q_EMIT layoutChanged();
241 }
242 
244 {
245  std::map<NodeId, int>::iterator it = priv->mapNodeRows.find(nodeid);
246  if (it == priv->mapNodeRows.end())
247  return -1;
248 
249  return it->second;
250 }
251 
252 void PeerTableModel::sort(int column, Qt::SortOrder order)
253 {
254  priv->sortColumn = column;
255  priv->sortOrder = order;
256  refresh();
257 }
CNodeStats::addrName
std::string addrName
Definition: net.h:253
PeerTableModel::Received
@ Received
Definition: peertablemodel.h:67
NodeId
int64_t NodeId
Definition: net.h:90
PeerTableModel::PeerTableModel
PeerTableModel(interfaces::Node &node, QObject *parent)
Definition: peertablemodel.cpp:104
CNodeStats::fInbound
bool fInbound
Definition: net.h:256
PeerTablePriv::mapNodeRows
std::map< NodeId, int > mapNodeRows
Index of rows by node ID.
Definition: peertablemodel.cpp:58
CNodeStats::m_network
Network m_network
Definition: net.h:275
PeerTableModel::NetNodeId
@ NetNodeId
Definition: peertablemodel.h:61
PeerTableModel::data
QVariant data(const QModelIndex &index, int role) const override
Definition: peertablemodel.cpp:151
CNodeStats::nodeid
NodeId nodeid
Definition: net.h:244
PeerTableModel::headerData
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
Definition: peertablemodel.cpp:206
CNodeCombinedStats::nodeStats
CNodeStats nodeStats
Definition: peertablemodel.h:27
PeerTablePriv::sortColumn
int sortColumn
Column to sort nodes by (default to unsorted)
Definition: peertablemodel.cpp:54
NodeLessThan::operator()
bool operator()(const CNodeCombinedStats &left, const CNodeCombinedStats &right) const
Definition: peertablemodel.cpp:18
PeerTableModel::index
QModelIndex index(int row, int column, const QModelIndex &parent) const override
Definition: peertablemodel.cpp:226
PeerTablePriv::sortOrder
Qt::SortOrder sortOrder
Order (ascending or descending) to sort nodes by.
Definition: peertablemodel.cpp:56
PeerTableModel::Subversion
@ Subversion
Definition: peertablemodel.h:68
NodeLessThan::column
int column
Definition: peertablemodel.h:41
PeerTablePriv
Definition: peertablemodel.cpp:48
PeerTablePriv::refreshPeers
void refreshPeers(interfaces::Node &node)
Pull a full list of peers from vNodes into our cache.
Definition: peertablemodel.cpp:61
PeerTableModel::Address
@ Address
Definition: peertablemodel.h:62
CNodeStats::m_min_ping_time
std::chrono::microseconds m_min_ping_time
Definition: net.h:266
PeerTableModel::priv
std::unique_ptr< PeerTablePriv > priv
Definition: peertablemodel.h:92
GUIUtil::ConnectionTypeToQString
QString ConnectionTypeToQString(ConnectionType conn_type, bool prepend_direction)
Convert enum ConnectionType to QString.
Definition: guiutil.cpp:665
interfaces::Node::NodesStats
std::vector< std::tuple< CNodeStats, bool, CNodeStateStats > > NodesStats
Get stats for connected nodes.
Definition: node.h:95
PeerTableModel::flags
Qt::ItemFlags flags(const QModelIndex &index) const override
Definition: peertablemodel.cpp:218
node.h
PeerTableModel::m_node
interfaces::Node & m_node
Definition: peertablemodel.h:90
CNodeCombinedStats::fNodeStateStatsAvailable
bool fNodeStateStatsAvailable
Definition: peertablemodel.h:29
PeerTablePriv::size
int size() const
Definition: peertablemodel.cpp:90
guiutil.h
CNodeStats::cleanSubVer
std::string cleanSubVer
Definition: net.h:255
m_node
NodeContext & m_node
Definition: interfaces.cpp:712
PeerTableModel::~PeerTableModel
~PeerTableModel()
Definition: peertablemodel.cpp:120
CNodeCombinedStats
Definition: peertablemodel.h:26
GUIUtil::formatBytes
QString formatBytes(uint64_t bytes)
Definition: guiutil.cpp:765
NodeLessThan::order
Qt::SortOrder order
Definition: peertablemodel.h:42
CNodeStats::m_conn_type
ConnectionType m_conn_type
Definition: net.h:277
interfaces::Node
Top-level interface for a bitcoin node (bitcoind process).
Definition: node.h:53
PeerTablePriv::cachedNodeStats
QList< CNodeCombinedStats > cachedNodeStats
Local cache of peer information.
Definition: peertablemodel.cpp:52
PeerTableModel::Ping
@ Ping
Definition: peertablemodel.h:65
PeerTableModel::refresh
void refresh()
Definition: peertablemodel.cpp:236
PeerTableModel::StatsRole
@ StatsRole
Definition: peertablemodel.h:72
PeerTableModel::columns
const QStringList columns
Definition: peertablemodel.h:91
CNodeStats::nSendBytes
uint64_t nSendBytes
Definition: net.h:260
guiconstants.h
PeerTableModel::Sent
@ Sent
Definition: peertablemodel.h:66
PeerTableModel::startAutoRefresh
void startAutoRefresh()
Definition: peertablemodel.cpp:125
GUIUtil::NetworkToQString
QString NetworkToQString(Network net)
Convert enum Network to QString.
Definition: guiutil.cpp:650
NodeLessThan
Definition: peertablemodel.h:33
PeerTableModel::sort
void sort(int column, Qt::SortOrder order) override
Definition: peertablemodel.cpp:252
node
Definition: interfaces.cpp:66
CNodeStats::nRecvBytes
uint64_t nRecvBytes
Definition: net.h:262
PeerTableModel::getRowByNodeId
int getRowByNodeId(NodeId nodeid)
Definition: peertablemodel.cpp:243
peertablemodel.h
PeerTableModel::Network
@ Network
Definition: peertablemodel.h:64
GUIUtil::formatPingTime
QString formatPingTime(std::chrono::microseconds ping_time)
Format a CNodeStats.m_last_ping_time into a user-readable string or display N/A, if 0.
Definition: guiutil.cpp:716
PeerTableModel::stopAutoRefresh
void stopAutoRefresh()
Definition: peertablemodel.cpp:130
assert
assert(std::addressof(::ChainstateActive().CoinsTip())==std::addressof(coins_cache))
CNodeStats
Definition: net.h:241
PeerTableModel::timer
QTimer * timer
Definition: peertablemodel.h:93
PeerTableModel::ConnectionType
@ ConnectionType
Definition: peertablemodel.h:63
PeerTablePriv::index
CNodeCombinedStats * index(int idx)
Definition: peertablemodel.cpp:95
PeerTableModel::columnCount
int columnCount(const QModelIndex &parent) const override
Definition: peertablemodel.cpp:143
it
auto it
Definition: validation.cpp:399
PeerTableModel::ColumnIndex
ColumnIndex
Definition: peertablemodel.h:60
MODEL_UPDATE_DELAY
static const int MODEL_UPDATE_DELAY
Definition: guiconstants.h:11
PeerTableModel::rowCount
int rowCount(const QModelIndex &parent) const override
Definition: peertablemodel.cpp:135
CNodeCombinedStats::nodeStateStats
CNodeStateStats nodeStateStats
Definition: peertablemodel.h:28