Bitcoin ABC  0.26.3
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
49 public:
51  QList<CNodeCombinedStats> cachedNodeStats;
53  int sortColumn{-1};
55  Qt::SortOrder sortOrder;
57  std::map<NodeId, int> mapNodeRows;
58 
61  {
62  cachedNodeStats.clear();
63 
64  interfaces::Node::NodesStats nodes_stats;
65  node.getNodesStats(nodes_stats);
66  cachedNodeStats.reserve(nodes_stats.size());
67  for (const auto &node_stats : nodes_stats) {
68  CNodeCombinedStats 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 
128 int PeerTableModel::rowCount(const QModelIndex &parent) const {
129  Q_UNUSED(parent);
130  return priv->size();
131 }
132 
133 int PeerTableModel::columnCount(const QModelIndex &parent) const {
134  Q_UNUSED(parent);
135  return columns.length();
136 }
137 
138 QVariant 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 
182 QVariant 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 
192 Qt::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 
201 QModelIndex 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 
231 void 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)
CNodeCombinedStats * index(int idx)
void refreshPeers(interfaces::Node &node)
Pull a full list of peers from vNodes into our cache.
QList< CNodeCombinedStats > cachedNodeStats
Local cache of peer information.
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:57
std::vector< std::tuple< CNodeStats, bool, CNodeStateStats > > NodesStats
Get stats for connected nodes.
Definition: node.h:99
static const int MODEL_UPDATE_DELAY
Definition: guiconstants.h:11
QString NetworkToQString(Network net)
Convert enum Network to QString.
Definition: guiutil.cpp:782
QString formatBytes(uint64_t bytes)
Definition: guiutil.cpp:886
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:844
Definition: init.h:28
NodeContext & m_node
Definition: interfaces.cpp:766
int64_t NodeId
Definition: nodeid.h:10
CNodeStateStats nodeStateStats
CNodeStats nodeStats
POD that contains various stats about a node.
Definition: net.h:272
uint64_t nRecvBytes
Definition: net.h:293
bool fInbound
Definition: net.h:286
uint64_t nSendBytes
Definition: net.h:291
std::chrono::microseconds m_min_ping_time
Definition: net.h:298
std::string m_addr_name
Definition: net.h:283
Network m_network
Definition: net.h:307
NodeId nodeid
Definition: net.h:273
std::string cleanSubVer
Definition: net.h:285