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  // prepend to peer address down-arrow symbol for inbound connection and up-arrow for outbound connection
76  return QString::fromStdString((rec->nodeStats.fInbound ? "↓ " : "↑ ") + rec->nodeStats.addrName);
77  case ConnectionType:
78  return GUIUtil::ConnectionTypeToQString(rec->nodeStats.m_conn_type, /* prepend_direction */ false);
79  case Network:
81  case Ping:
83  case Sent:
85  case Received:
87  case Subversion:
88  return QString::fromStdString(rec->nodeStats.cleanSubVer);
89  } // no default case, so the compiler can warn about missing cases
90  assert(false);
91  } else if (role == Qt::TextAlignmentRole) {
92  switch (column) {
93  case NetNodeId:
94  return QVariant(Qt::AlignRight | Qt::AlignVCenter);
95  case Address:
96  return {};
97  case ConnectionType:
98  case Network:
99  return QVariant(Qt::AlignCenter);
100  case Ping:
101  case Sent:
102  case Received:
103  return QVariant(Qt::AlignRight | Qt::AlignVCenter);
104  case Subversion:
105  return {};
106  } // no default case, so the compiler can warn about missing cases
107  assert(false);
108  } else if (role == StatsRole) {
109  return QVariant::fromValue(rec);
110  }
111 
112  return QVariant();
113 }
114 
115 QVariant PeerTableModel::headerData(int section, Qt::Orientation orientation, int role) const
116 {
117  if(orientation == Qt::Horizontal)
118  {
119  if(role == Qt::DisplayRole && section < columns.size())
120  {
121  return columns[section];
122  }
123  }
124  return QVariant();
125 }
126 
127 Qt::ItemFlags PeerTableModel::flags(const QModelIndex &index) const
128 {
129  if (!index.isValid()) return Qt::NoItemFlags;
130 
131  Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
132  return retval;
133 }
134 
135 QModelIndex PeerTableModel::index(int row, int column, const QModelIndex& parent) const
136 {
137  Q_UNUSED(parent);
138 
139  if (0 <= row && row < rowCount() && 0 <= column && column < columnCount()) {
140  return createIndex(row, column, const_cast<CNodeCombinedStats*>(&m_peers_data[row]));
141  }
142 
143  return QModelIndex();
144 }
145 
147 {
148  interfaces::Node::NodesStats nodes_stats;
149  m_node.getNodesStats(nodes_stats);
150  decltype(m_peers_data) new_peers_data;
151  new_peers_data.reserve(nodes_stats.size());
152  for (const auto& node_stats : nodes_stats) {
153  const CNodeCombinedStats stats{std::get<0>(node_stats), std::get<2>(node_stats), std::get<1>(node_stats)};
154  new_peers_data.append(stats);
155  }
156 
157  // Handle peer addition or removal as suggested in Qt Docs. See:
158  // - https://doc.qt.io/qt-5/model-view-programming.html#inserting-and-removing-rows
159  // - https://doc.qt.io/qt-5/model-view-programming.html#resizable-models
160  // We take advantage of the fact that the std::vector returned
161  // by interfaces::Node::getNodesStats is sorted by nodeid.
162  for (int i = 0; i < m_peers_data.size();) {
163  if (i < new_peers_data.size() && m_peers_data.at(i).nodeStats.nodeid == new_peers_data.at(i).nodeStats.nodeid) {
164  ++i;
165  continue;
166  }
167  // A peer has been removed from the table.
168  beginRemoveRows(QModelIndex(), i, i);
169  m_peers_data.erase(m_peers_data.begin() + i);
170  endRemoveRows();
171  }
172 
173  if (m_peers_data.size() < new_peers_data.size()) {
174  // Some peers have been added to the end of the table.
175  beginInsertRows(QModelIndex(), m_peers_data.size(), new_peers_data.size() - 1);
176  m_peers_data.swap(new_peers_data);
177  endInsertRows();
178  } else {
179  m_peers_data.swap(new_peers_data);
180  }
181 
182  const auto top_left = index(0, 0);
183  const auto bottom_right = index(rowCount() - 1, columnCount() - 1);
184  Q_EMIT dataChanged(top_left, bottom_right);
185 }
CNodeStats::addrName
std::string addrName
Definition: net.h:251
PeerTableModel::Received
@ Received
Definition: peertablemodel.h:55
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:115
CNodeStats::fInbound
bool fInbound
Definition: net.h:254
PeerTableModel::data
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Definition: peertablemodel.cpp:62
CNodeStats::m_network
Network m_network
Definition: net.h:273
PeerTableModel::NetNodeId
@ NetNodeId
Definition: peertablemodel.h:49
CNodeStats::nodeid
NodeId nodeid
Definition: net.h:242
CNodeCombinedStats::nodeStats
CNodeStats nodeStats
Definition: peertablemodel.h:28
m_node
NodeContext & m_node
Definition: bitcoin-node.cpp:29
PeerTableModel::columnCount
int columnCount(const QModelIndex &parent=QModelIndex()) const override
Definition: peertablemodel.cpp:54
PeerTableModel::Subversion
@ Subversion
Definition: peertablemodel.h:56
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:264
PeerTableModel::m_peers_data
QList< CNodeCombinedStats > m_peers_data
Internal peer data structure.
Definition: peertablemodel.h:78
GUIUtil::ConnectionTypeToQString
QString ConnectionTypeToQString(ConnectionType conn_type, bool prepend_direction)
Convert enum ConnectionType to QString.
Definition: guiutil.cpp:672
interfaces::Node::NodesStats
std::vector< std::tuple< CNodeStats, bool, CNodeStateStats > > NodesStats
Get stats for connected nodes.
Definition: node.h:96
PeerTableModel::flags
Qt::ItemFlags flags(const QModelIndex &index) const override
Definition: peertablemodel.cpp:127
node.h
PeerTableModel::m_node
interfaces::Node & m_node
Definition: peertablemodel.h:79
guiutil.h
CNodeStats::cleanSubVer
std::string cleanSubVer
Definition: net.h:253
PeerTableModel::~PeerTableModel
~PeerTableModel()
Definition: peertablemodel.cpp:31
CNodeCombinedStats
Definition: peertablemodel.h:27
GUIUtil::formatBytes
QString formatBytes(uint64_t bytes)
Definition: guiutil.cpp:772
CNodeStats::m_conn_type
ConnectionType m_conn_type
Definition: net.h:275
interfaces::Node
Top-level interface for a bitcoin node (bitcoind process).
Definition: node.h:54
PeerTableModel::Ping
@ Ping
Definition: peertablemodel.h:53
interfaces::Node::getNodesStats
virtual bool getNodesStats(NodesStats &stats)=0
PeerTableModel::refresh
void refresh()
Definition: peertablemodel.cpp:146
PeerTableModel::StatsRole
@ StatsRole
Definition: peertablemodel.h:60
PeerTableModel::index
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Definition: peertablemodel.cpp:135
PeerTableModel::columns
const QStringList columns
Definition: peertablemodel.h:80
CNodeStats::nSendBytes
uint64_t nSendBytes
Definition: net.h:258
guiconstants.h
PeerTableModel::Sent
@ Sent
Definition: peertablemodel.h:54
PeerTableModel::startAutoRefresh
void startAutoRefresh()
Definition: peertablemodel.cpp:36
GUIUtil::NetworkToQString
QString NetworkToQString(Network net)
Convert enum Network to QString.
Definition: guiutil.cpp:657
node
Definition: interfaces.cpp:68
assert
assert(s1.IsAddrV1Compatible())
CNodeStats::nRecvBytes
uint64_t nRecvBytes
Definition: net.h:260
peertablemodel.h
PeerTableModel::Network
@ Network
Definition: peertablemodel.h:52
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:723
PeerTableModel::stopAutoRefresh
void stopAutoRefresh()
Definition: peertablemodel.cpp:41
PeerTableModel::timer
QTimer * timer
Definition: peertablemodel.h:105
PeerTableModel::ConnectionType
@ ConnectionType
Definition: peertablemodel.h:51
PeerTableModel::ColumnIndex
ColumnIndex
Definition: peertablemodel.h:48
MODEL_UPDATE_DELAY
static const int MODEL_UPDATE_DELAY
Definition: guiconstants.h:11