14
14
#include < QList>
15
15
#include < QTimer>
16
16
17
- // private implementation
18
- class PeerTablePriv
19
- {
20
- public:
21
- /* * Local cache of peer information */
22
- QList<CNodeCombinedStats> cachedNodeStats;
23
-
24
- /* * Pull a full list of peers from vNodes into our cache */
25
- void refreshPeers (interfaces::Node& node)
26
- {
27
- cachedNodeStats.clear ();
28
-
29
- interfaces::Node::NodesStats nodes_stats;
30
- node.getNodesStats (nodes_stats);
31
- cachedNodeStats.reserve (nodes_stats.size ());
32
- for (const auto & node_stats : nodes_stats)
33
- {
34
- CNodeCombinedStats stats;
35
- stats.nodeStats = std::get<0 >(node_stats);
36
- stats.fNodeStateStatsAvailable = std::get<1 >(node_stats);
37
- stats.nodeStateStats = std::get<2 >(node_stats);
38
- cachedNodeStats.append (stats);
39
- }
40
- }
41
-
42
- int size () const
43
- {
44
- return cachedNodeStats.size ();
45
- }
46
-
47
- CNodeCombinedStats *index (int idx)
48
- {
49
- if (idx >= 0 && idx < cachedNodeStats.size ())
50
- return &cachedNodeStats[idx];
51
-
52
- return nullptr ;
53
- }
54
- };
55
-
56
17
PeerTableModel::PeerTableModel (interfaces::Node& node, QObject* parent) :
57
18
QAbstractTableModel(parent),
58
19
m_node(node),
59
20
timer(nullptr )
60
21
{
61
- priv.reset (new PeerTablePriv ());
62
-
63
22
// set up timer for auto refresh
64
23
timer = new QTimer (this );
65
24
connect (timer, &QTimer::timeout, this , &PeerTableModel::refresh);
@@ -84,23 +43,23 @@ void PeerTableModel::stopAutoRefresh()
84
43
timer->stop ();
85
44
}
86
45
87
- int PeerTableModel::rowCount (const QModelIndex & parent) const
46
+ int PeerTableModel::rowCount (const QModelIndex& parent) const
88
47
{
89
48
if (parent.isValid ()) {
90
49
return 0 ;
91
50
}
92
- return priv-> size ();
51
+ return m_peers_data. size ();
93
52
}
94
53
95
- int PeerTableModel::columnCount (const QModelIndex & parent) const
54
+ int PeerTableModel::columnCount (const QModelIndex& parent) const
96
55
{
97
56
if (parent.isValid ()) {
98
57
return 0 ;
99
58
}
100
59
return columns.length ();
101
60
}
102
61
103
- QVariant PeerTableModel::data (const QModelIndex & index, int role) const
62
+ QVariant PeerTableModel::data (const QModelIndex& index, int role) const
104
63
{
105
64
if (!index .isValid ())
106
65
return QVariant ();
@@ -173,19 +132,52 @@ Qt::ItemFlags PeerTableModel::flags(const QModelIndex &index) const
173
132
return retval;
174
133
}
175
134
176
- QModelIndex PeerTableModel::index (int row, int column, const QModelIndex & parent) const
135
+ QModelIndex PeerTableModel::index (int row, int column, const QModelIndex& parent) const
177
136
{
178
137
Q_UNUSED (parent);
179
- CNodeCombinedStats *data = priv->index (row);
180
138
181
- if (data)
182
- return createIndex (row, column, data);
139
+ if (0 <= row && row < rowCount () && 0 <= column && column < columnCount ()) {
140
+ return createIndex (row, column, const_cast <CNodeCombinedStats*>(&m_peers_data[row]));
141
+ }
142
+
183
143
return QModelIndex ();
184
144
}
185
145
186
146
void PeerTableModel::refresh ()
187
147
{
188
- Q_EMIT layoutAboutToBeChanged ();
189
- priv->refreshPeers (m_node);
190
- Q_EMIT layoutChanged ();
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
+ Q_EMIT changed ();
191
183
}
0 commit comments