Bitcoin Core  22.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 <QList>
15 #include <QTimer>
16 
18  QAbstractTableModel(parent),
19  m_node(node),
20  timer(nullptr)
21 {
22  // set up timer for auto refresh
23  timer = new QTimer(this);
24  connect(timer, &QTimer::timeout, this, &PeerTableModel::refresh);
25  timer->setInterval(MODEL_UPDATE_DELAY);
26 
27  // load initial data
28  refresh();
29 }
30 
32 {
33  // Intentionally left empty
34 }
35 
37 {
38  timer->start();
39 }
40 
42 {
43  timer->stop();
44 }
45 
46 int PeerTableModel::rowCount(const QModelIndex& parent) const
47 {
48  if (parent.isValid()) {
49  return 0;
50  }
51  return m_peers_data.size();
52 }
53 
54 int PeerTableModel::columnCount(const QModelIndex& parent) const
55 {
56  if (parent.isValid()) {
57  return 0;
58  }
59  return columns.length();
60 }
61 
62 QVariant PeerTableModel::data(const QModelIndex& index, int role) const
63 {
64  if(!index.isValid())
65  return QVariant();
66 
67  CNodeCombinedStats *rec = static_cast<CNodeCombinedStats*>(index.internalPointer());
68 
69  const auto column = static_cast<ColumnIndex>(index.column());
70  if (role == Qt::DisplayRole) {
71  switch (column) {
72  case NetNodeId:
73  return (qint64)rec->nodeStats.nodeid;
74  case Address:
75  return QString::fromStdString(rec->nodeStats.m_addr_name);
76  case Direction:
77  return QString(rec->nodeStats.fInbound ?
78  //: An Inbound Connection from a Peer.
79  tr("Inbound") :
80  //: An Outbound Connection to a Peer.
81  tr("Outbound"));
82  case ConnectionType:
83  return GUIUtil::ConnectionTypeToQString(rec->nodeStats.m_conn_type, /* prepend_direction */ false);
84  case Network:
86  case Ping:
88  case Sent:
90  case Received:
92  case Subversion:
93  return QString::fromStdString(rec->nodeStats.cleanSubVer);
94  } // no default case, so the compiler can warn about missing cases
95  assert(false);
96  } else if (role == Qt::TextAlignmentRole) {
97  switch (column) {
98  case NetNodeId:
99  return QVariant(Qt::AlignRight | Qt::AlignVCenter);
100  case Address:
101  return {};
102  case Direction:
103  case ConnectionType:
104  case Network:
105  return QVariant(Qt::AlignCenter);
106  case Ping:
107  case Sent:
108  case Received:
109  return QVariant(Qt::AlignRight | Qt::AlignVCenter);
110  case Subversion:
111  return {};
112  } // no default case, so the compiler can warn about missing cases
113  assert(false);
114  } else if (role == StatsRole) {
115  return QVariant::fromValue(rec);
116  }
117 
118  return QVariant();
119 }
120 
121 QVariant PeerTableModel::headerData(int section, Qt::Orientation orientation, int role) const
122 {
123  if(orientation == Qt::Horizontal)
124  {
125  if(role == Qt::DisplayRole && section < columns.size())
126  {
127  return columns[section];
128  }
129  }
130  return QVariant();
131 }
132 
133 Qt::ItemFlags PeerTableModel::flags(const QModelIndex &index) const
134 {
135  if (!index.isValid()) return Qt::NoItemFlags;
136 
137  Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
138  return retval;
139 }
140 
141 QModelIndex PeerTableModel::index(int row, int column, const QModelIndex& parent) const
142 {
143  Q_UNUSED(parent);
144 
145  if (0 <= row && row < rowCount() && 0 <= column && column < columnCount()) {
146  return createIndex(row, column, const_cast<CNodeCombinedStats*>(&m_peers_data[row]));
147  }
148 
149  return QModelIndex();
150 }
151 
153 {
154  interfaces::Node::NodesStats nodes_stats;
155  m_node.getNodesStats(nodes_stats);
156  decltype(m_peers_data) new_peers_data;
157  new_peers_data.reserve(nodes_stats.size());
158  for (const auto& node_stats : nodes_stats) {
159  const CNodeCombinedStats stats{std::get<0>(node_stats), std::get<2>(node_stats), std::get<1>(node_stats)};
160  new_peers_data.append(stats);
161  }
162 
163  // Handle peer addition or removal as suggested in Qt Docs. See:
164  // - https://doc.qt.io/qt-5/model-view-programming.html#inserting-and-removing-rows
165  // - https://doc.qt.io/qt-5/model-view-programming.html#resizable-models
166  // We take advantage of the fact that the std::vector returned
167  // by interfaces::Node::getNodesStats is sorted by nodeid.
168  for (int i = 0; i < m_peers_data.size();) {
169  if (i < new_peers_data.size() && m_peers_data.at(i).nodeStats.nodeid == new_peers_data.at(i).nodeStats.nodeid) {
170  ++i;
171  continue;
172  }
173  // A peer has been removed from the table.
174  beginRemoveRows(QModelIndex(), i, i);
175  m_peers_data.erase(m_peers_data.begin() + i);
176  endRemoveRows();
177  }
178 
179  if (m_peers_data.size() < new_peers_data.size()) {
180  // Some peers have been added to the end of the table.
181  beginInsertRows(QModelIndex(), m_peers_data.size(), new_peers_data.size() - 1);
182  m_peers_data.swap(new_peers_data);
183  endInsertRows();
184  } else {
185  m_peers_data.swap(new_peers_data);
186  }
187 
188  const auto top_left = index(0, 0);
189  const auto bottom_right = index(rowCount() - 1, columnCount() - 1);
190  Q_EMIT dataChanged(top_left, bottom_right);
191 }
PeerTableModel::Received
@ Received
Definition: peertablemodel.h:56
PeerTableModel::PeerTableModel
PeerTableModel(interfaces::Node &node, QObject *parent)
Definition: peertablemodel.cpp:17
PeerTableModel::headerData
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
Definition: peertablemodel.cpp:121
CNodeStats::fInbound
bool fInbound
Definition: net.h:253
PeerTableModel::data
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Definition: peertablemodel.cpp:62
assert
assert(!tx.IsCoinBase())
CNodeStats::m_network
Network m_network
Definition: net.h:272
PeerTableModel::NetNodeId
@ NetNodeId
Definition: peertablemodel.h:49
CNodeStats::nodeid
NodeId nodeid
Definition: net.h:241
CNodeCombinedStats::nodeStats
CNodeStats nodeStats
Definition: peertablemodel.h:28
PeerTableModel::columnCount
int columnCount(const QModelIndex &parent=QModelIndex()) const override
Definition: peertablemodel.cpp:54
PeerTableModel::Subversion
@ Subversion
Definition: peertablemodel.h:57
PeerTableModel::rowCount
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Definition: peertablemodel.cpp:46
PeerTableModel::Address
@ Address
Definition: peertablemodel.h:50
CNodeStats::m_min_ping_time
std::chrono::microseconds m_min_ping_time
Definition: net.h:263
PeerTableModel::Direction
@ Direction
Definition: peertablemodel.h:51
PeerTableModel::m_peers_data
QList< CNodeCombinedStats > m_peers_data
Internal peer data structure.
Definition: peertablemodel.h:79
GUIUtil::ConnectionTypeToQString
QString ConnectionTypeToQString(ConnectionType conn_type, bool prepend_direction)
Convert enum ConnectionType to QString.
Definition: guiutil.cpp:679
interfaces::Node::NodesStats
std::vector< std::tuple< CNodeStats, bool, CNodeStateStats > > NodesStats
Get stats for connected nodes.
Definition: node.h:106
CNodeStats::m_addr_name
std::string m_addr_name
Definition: net.h:250
PeerTableModel::flags
Qt::ItemFlags flags(const QModelIndex &index) const override
Definition: peertablemodel.cpp:133
node.h
PeerTableModel::m_node
interfaces::Node & m_node
Definition: peertablemodel.h:80
m_node
NodeContext m_node
Definition: bitcoin-gui.cpp:36
guiutil.h
CNodeStats::cleanSubVer
std::string cleanSubVer
Definition: net.h:252
PeerTableModel::~PeerTableModel
~PeerTableModel()
Definition: peertablemodel.cpp:31
CNodeCombinedStats
Definition: peertablemodel.h:27
GUIUtil::formatBytes
QString formatBytes(uint64_t bytes)
Definition: guiutil.cpp:791
CNodeStats::m_conn_type
ConnectionType m_conn_type
Definition: net.h:274
interfaces::Node
Top-level interface for a bitcoin node (bitcoind process).
Definition: node.h:64
PeerTableModel::Ping
@ Ping
Definition: peertablemodel.h:54
interfaces::Node::getNodesStats
virtual bool getNodesStats(NodesStats &stats)=0
PeerTableModel::refresh
void refresh()
Definition: peertablemodel.cpp:152
PeerTableModel::StatsRole
@ StatsRole
Definition: peertablemodel.h:61
PeerTableModel::index
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Definition: peertablemodel.cpp:141
PeerTableModel::columns
const QStringList columns
Definition: peertablemodel.h:81
CNodeStats::nSendBytes
uint64_t nSendBytes
Definition: net.h:257
guiconstants.h
PeerTableModel::Sent
@ Sent
Definition: peertablemodel.h:55
PeerTableModel::startAutoRefresh
void startAutoRefresh()
Definition: peertablemodel.cpp:36
GUIUtil::NetworkToQString
QString NetworkToQString(Network net)
Convert enum Network to QString.
Definition: guiutil.cpp:664
node
Definition: interfaces.cpp:68
CNodeStats::nRecvBytes
uint64_t nRecvBytes
Definition: net.h:259
peertablemodel.h
PeerTableModel::Network
@ Network
Definition: peertablemodel.h:53
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:742
PeerTableModel::stopAutoRefresh
void stopAutoRefresh()
Definition: peertablemodel.cpp:41
PeerTableModel::timer
QTimer * timer
Definition: peertablemodel.h:109
PeerTableModel::ConnectionType
@ ConnectionType
Definition: peertablemodel.h:52
PeerTableModel::ColumnIndex
ColumnIndex
Definition: peertablemodel.h:48
MODEL_UPDATE_DELAY
static const int MODEL_UPDATE_DELAY
Definition: guiconstants.h:11