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
46int PeerTableModel::rowCount(const QModelIndex& parent) const
47{
48 if (parent.isValid()) {
49 return 0;
50 }
51 return m_peers_data.size();
52}
53
54int PeerTableModel::columnCount(const QModelIndex& parent) const
55{
56 if (parent.isValid()) {
57 return 0;
58 }
59 return columns.length();
60}
61
62QVariant 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
121QVariant 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
133Qt::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
141QModelIndex 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{
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}
NodeContext m_node
Definition: bitcoin-gui.cpp:36
uint64_t nRecvBytes
Definition: net.h:259
bool fInbound
Definition: net.h:253
uint64_t nSendBytes
Definition: net.h:257
ConnectionType m_conn_type
Definition: net.h:274
std::chrono::microseconds m_min_ping_time
Definition: net.h:263
std::string m_addr_name
Definition: net.h:250
Network m_network
Definition: net.h:272
NodeId nodeid
Definition: net.h:241
std::string cleanSubVer
Definition: net.h:252
int columnCount(const QModelIndex &parent=QModelIndex()) const override
Qt::ItemFlags flags(const QModelIndex &index) const override
int rowCount(const QModelIndex &parent=QModelIndex()) const override
interfaces::Node & m_node
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
QList< CNodeCombinedStats > m_peers_data
Internal peer data structure.
const QStringList columns
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
PeerTableModel(interfaces::Node &node, QObject *parent)
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Top-level interface for a bitcoin node (bitcoind process).
Definition: node.h:55
std::vector< std::tuple< CNodeStats, bool, CNodeStateStats > > NodesStats
Get stats for connected nodes.
Definition: node.h:96
virtual bool getNodesStats(NodesStats &stats)=0
static const int MODEL_UPDATE_DELAY
Definition: guiconstants.h:11
QString NetworkToQString(Network net)
Convert enum Network to QString.
Definition: guiutil.cpp:664
QString formatBytes(uint64_t bytes)
Definition: guiutil.cpp:791
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
QString ConnectionTypeToQString(ConnectionType conn_type, bool prepend_direction)
Convert enum ConnectionType to QString.
Definition: guiutil.cpp:679
CNodeStats nodeStats
assert(!tx.IsCoinBase())