Bitcoin ABC 0.30.5
P2P Digital Currency
peertablemodel.cpp
Go to the documentation of this file.
1// Copyright (c) 2011-2016 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
19 const CNodeCombinedStats &right) const {
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
27 switch (column) {
29 return pLeft->nodeid < pRight->nodeid;
31 return pLeft->m_addr_name.compare(pRight->m_addr_name) < 0;
33 return pLeft->m_network < pRight->m_network;
35 return pLeft->m_min_ping_time < pRight->m_min_ping_time;
37 return pLeft->nSendBytes < pRight->nSendBytes;
39 return pLeft->nRecvBytes < pRight->nRecvBytes;
41 return pLeft->cleanSubVer.compare(pRight->cleanSubVer) < 0;
42 }
43
44 return false;
45}
46
47// private implementation
49public:
51 QList<CNodeCombinedStats> cachedNodeStats;
53 int sortColumn{-1};
55 Qt::SortOrder sortOrder;
57 std::map<NodeId, int> mapNodeRows;
58
61 {
62 cachedNodeStats.clear();
63
65 node.getNodesStats(nodes_stats);
66 cachedNodeStats.reserve(nodes_stats.size());
67 for (const auto &node_stats : nodes_stats) {
69 stats.nodeStats = std::get<0>(node_stats);
70 stats.fNodeStateStatsAvailable = std::get<1>(node_stats);
71 stats.nodeStateStats = std::get<2>(node_stats);
72 cachedNodeStats.append(stats);
73 }
74 }
75
76 if (sortColumn >= 0) {
77 // sort cacheNodeStats (use stable sort to prevent rows jumping
78 // around unnecessarily)
79 std::stable_sort(cachedNodeStats.begin(), cachedNodeStats.end(),
81 }
82
83 // build index map
84 mapNodeRows.clear();
85 int row = 0;
86 for (const CNodeCombinedStats &stats : cachedNodeStats) {
87 mapNodeRows.insert(
88 std::pair<NodeId, int>(stats.nodeStats.nodeid, row++));
89 }
90 }
91
92 int size() const { return cachedNodeStats.size(); }
93
95 if (idx >= 0 && idx < cachedNodeStats.size()) {
96 return &cachedNodeStats[idx];
97 }
98
99 return nullptr;
100 }
101};
102
104 : QAbstractTableModel(parent), m_node(node), timer(nullptr) {
105 priv.reset(new PeerTablePriv());
106
107 // set up timer for auto refresh
108 timer = new QTimer(this);
109 connect(timer, &QTimer::timeout, this, &PeerTableModel::refresh);
110 timer->setInterval(MODEL_UPDATE_DELAY);
111
112 // load initial data
113 refresh();
114}
115
117 // Intentionally left empty
118}
119
121 timer->start();
122}
123
125 timer->stop();
126}
127
128int PeerTableModel::rowCount(const QModelIndex &parent) const {
129 Q_UNUSED(parent);
130 return priv->size();
131}
132
133int PeerTableModel::columnCount(const QModelIndex &parent) const {
134 Q_UNUSED(parent);
135 return columns.length();
136}
137
138QVariant PeerTableModel::data(const QModelIndex &index, int role) const {
139 if (!index.isValid()) {
140 return QVariant();
141 }
142
143 CNodeCombinedStats *rec =
144 static_cast<CNodeCombinedStats *>(index.internalPointer());
145
146 if (role == Qt::DisplayRole) {
147 switch (index.column()) {
148 case NetNodeId:
149 return (qint64)rec->nodeStats.nodeid;
150 case Address:
151 // prepend to peer address down-arrow symbol for inbound
152 // connection and up-arrow for outbound connection
153 return QString(rec->nodeStats.fInbound ? "↓ " : "↑ ") +
154 QString::fromStdString(rec->nodeStats.m_addr_name);
155 case Network:
157 case Ping:
159 case Sent:
161 case Received:
163 case Subversion:
164 return QString::fromStdString(rec->nodeStats.cleanSubVer);
165 }
166 } else if (role == Qt::TextAlignmentRole) {
167 switch (index.column()) {
168 case Network:
169 return QVariant(Qt::AlignCenter);
170 case Ping:
171 case Sent:
172 case Received:
173 return QVariant(Qt::AlignRight | Qt::AlignVCenter);
174 default:
175 return QVariant();
176 }
177 }
178
179 return QVariant();
180}
181
182QVariant PeerTableModel::headerData(int section, Qt::Orientation orientation,
183 int role) const {
184 if (orientation == Qt::Horizontal) {
185 if (role == Qt::DisplayRole && section < columns.size()) {
186 return columns[section];
187 }
188 }
189 return QVariant();
190}
191
192Qt::ItemFlags PeerTableModel::flags(const QModelIndex &index) const {
193 if (!index.isValid()) {
194 return Qt::NoItemFlags;
195 }
196
197 Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
198 return retval;
199}
200
201QModelIndex PeerTableModel::index(int row, int column,
202 const QModelIndex &parent) const {
203 Q_UNUSED(parent);
204 CNodeCombinedStats *data = priv->index(row);
205
206 if (data) {
207 return createIndex(row, column, data);
208 }
209 return QModelIndex();
210}
211
213 return priv->index(idx);
214}
215
217 Q_EMIT layoutAboutToBeChanged();
218 priv->refreshPeers(m_node);
219 Q_EMIT layoutChanged();
220}
221
223 std::map<NodeId, int>::iterator it = priv->mapNodeRows.find(nodeid);
224 if (it == priv->mapNodeRows.end()) {
225 return -1;
226 }
227
228 return it->second;
229}
230
231void PeerTableModel::sort(int column, Qt::SortOrder order) {
232 priv->sortColumn = column;
233 priv->sortOrder = order;
234 refresh();
235}
bool operator()(const CNodeCombinedStats &left, const CNodeCombinedStats &right) const
Qt::SortOrder order
QVariant data(const QModelIndex &index, int role) const override
int columnCount(const QModelIndex &parent) const override
Qt::ItemFlags flags(const QModelIndex &index) const override
interfaces::Node & m_node
QModelIndex index(int row, int column, const QModelIndex &parent) const override
void sort(int column, Qt::SortOrder order) override
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
const CNodeCombinedStats * getNodeStats(int idx)
const QStringList columns
PeerTableModel(interfaces::Node &node, QObject *parent)
int getRowByNodeId(NodeId nodeid)
int rowCount(const QModelIndex &parent) const override
std::unique_ptr< PeerTablePriv > priv
int sortColumn
Column to sort nodes by (default to unsorted)
void refreshPeers(interfaces::Node &node)
Pull a full list of peers from vNodes into our cache.
QList< CNodeCombinedStats > cachedNodeStats
Local cache of peer information.
CNodeCombinedStats * index(int idx)
int size() const
Qt::SortOrder sortOrder
Order (ascending or descending) to sort nodes by.
std::map< NodeId, int > mapNodeRows
Index of rows by node ID.
Top-level interface for a bitcoin node (bitcoind process).
Definition: node.h:59
std::vector< std::tuple< CNodeStats, bool, CNodeStateStats > > NodesStats
Get stats for connected nodes.
Definition: node.h:122
static const int MODEL_UPDATE_DELAY
Definition: guiconstants.h:11
QString NetworkToQString(Network net)
Convert enum Network to QString.
Definition: guiutil.cpp:789
QString formatBytes(uint64_t bytes)
Definition: guiutil.cpp:893
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:851
Definition: init.h:28
NodeContext & m_node
Definition: interfaces.cpp:785
int64_t NodeId
Definition: nodeid.h:10
CNodeStateStats nodeStateStats
CNodeStats nodeStats
POD that contains various stats about a node.
Definition: net.h:287
uint64_t nRecvBytes
Definition: net.h:307
bool fInbound
Definition: net.h:299
uint64_t nSendBytes
Definition: net.h:305
std::chrono::microseconds m_min_ping_time
Definition: net.h:311
std::string m_addr_name
Definition: net.h:296
Network m_network
Definition: net.h:319
NodeId nodeid
Definition: net.h:288
std::string cleanSubVer
Definition: net.h:298