Skip to content

Commit 9ca2aad

Browse files
hebastoknst
authored andcommitted
Merge bitcoin-core/gui#164: Handle peer addition/removal in a right way
ecbd911 qt: Handle peer addition/removal in a right way (Hennadii Stepanov) 1b66f6e qt: Drop PeerTablePriv class (Hennadii Stepanov) efb7e5a qt, refactor: Use default arguments for overridden functions (Hennadii Stepanov) Pull request description: This PR makes `PeerTableModel` handle a peer addition/removal in a right way. See: - https://doc.qt.io/qt-5/model-view-programming.html#inserting-and-removing-rows - https://doc.qt.io/qt-5/model-view-programming.html#resizable-models Fixes #160. Fixes #191. ACKs for top commit: jarolrod: re-ACK ecbd911 promag: reACK ecbd911 just improvements to the comment since last review. Tree-SHA512: 074935d67f78561724218e8b33822e2de16749f873c29054926b720ffcd642f08249a222b563983cf65a9b716290aa14e2372c47fc04e5f401f759db25ca710f
1 parent 7d9ce32 commit 9ca2aad

File tree

3 files changed

+58
-62
lines changed

3 files changed

+58
-62
lines changed

src/qt/peertablemodel.cpp

Lines changed: 44 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -14,53 +14,11 @@
1414
#include <QList>
1515
#include <QTimer>
1616

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-
33-
for (const auto& node_stats : nodes_stats)
34-
{
35-
CNodeCombinedStats stats;
36-
stats.nodeStats = std::get<0>(node_stats);
37-
stats.fNodeStateStatsAvailable = std::get<1>(node_stats);
38-
stats.nodeStateStats = std::get<2>(node_stats);
39-
cachedNodeStats.append(stats);
40-
}
41-
}
42-
43-
int size() const
44-
{
45-
return cachedNodeStats.size();
46-
}
47-
48-
CNodeCombinedStats *index(int idx)
49-
{
50-
if (idx >= 0 && idx < cachedNodeStats.size())
51-
return &cachedNodeStats[idx];
52-
53-
return nullptr;
54-
}
55-
};
56-
5717
PeerTableModel::PeerTableModel(interfaces::Node& node, QObject* parent) :
5818
QAbstractTableModel(parent),
5919
m_node(node),
6020
timer(nullptr)
6121
{
62-
priv.reset(new PeerTablePriv());
63-
6422
// set up timer for auto refresh
6523
timer = new QTimer(this);
6624
connect(timer, &QTimer::timeout, this, &PeerTableModel::refresh);
@@ -85,23 +43,23 @@ void PeerTableModel::stopAutoRefresh()
8543
timer->stop();
8644
}
8745

88-
int PeerTableModel::rowCount(const QModelIndex &parent) const
46+
int PeerTableModel::rowCount(const QModelIndex& parent) const
8947
{
9048
if (parent.isValid()) {
9149
return 0;
9250
}
93-
return priv->size();
51+
return m_peers_data.size();
9452
}
9553

96-
int PeerTableModel::columnCount(const QModelIndex &parent) const
54+
int PeerTableModel::columnCount(const QModelIndex& parent) const
9755
{
9856
if (parent.isValid()) {
9957
return 0;
10058
}
10159
return columns.length();
10260
}
10361

104-
QVariant PeerTableModel::data(const QModelIndex &index, int role) const
62+
QVariant PeerTableModel::data(const QModelIndex& index, int role) const
10563
{
10664
if(!index.isValid())
10765
return QVariant();
@@ -174,19 +132,52 @@ Qt::ItemFlags PeerTableModel::flags(const QModelIndex &index) const
174132
return retval;
175133
}
176134

177-
QModelIndex PeerTableModel::index(int row, int column, const QModelIndex &parent) const
135+
QModelIndex PeerTableModel::index(int row, int column, const QModelIndex& parent) const
178136
{
179137
Q_UNUSED(parent);
180-
CNodeCombinedStats *data = priv->index(row);
181138

182-
if (data)
183-
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+
184143
return QModelIndex();
185144
}
186145

187146
void PeerTableModel::refresh()
188147
{
189-
Q_EMIT layoutAboutToBeChanged();
190-
priv->refreshPeers(m_node);
191-
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();
192183
}

src/qt/peertablemodel.h

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88
#include <net_processing.h> // For CNodeStateStats
99
#include <net.h>
1010

11-
#include <memory>
12-
1311
#include <QAbstractTableModel>
12+
#include <QList>
13+
#include <QModelIndex>
1414
#include <QStringList>
15+
#include <QVariant>
1516

1617
class PeerTablePriv;
1718

@@ -61,18 +62,23 @@ class PeerTableModel : public QAbstractTableModel
6162

6263
/** @name Methods overridden from QAbstractTableModel
6364
@{*/
64-
int rowCount(const QModelIndex &parent) const override;
65-
int columnCount(const QModelIndex &parent) const override;
66-
QVariant data(const QModelIndex &index, int role) const override;
67-
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
68-
QModelIndex index(int row, int column, const QModelIndex &parent) const override;
65+
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
66+
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
67+
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
68+
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
69+
QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override;
6970
Qt::ItemFlags flags(const QModelIndex &index) const override;
7071
/*@}*/
7172

7273
public Q_SLOTS:
7374
void refresh();
7475

76+
Q_SIGNALS:
77+
void changed();
78+
7579
private:
80+
//! Internal peer data structure.
81+
QList<CNodeCombinedStats> m_peers_data{};
7682
interfaces::Node& m_node;
7783
const QStringList columns{
7884
/*: Title of Peers Table column which contains a
@@ -99,7 +105,6 @@ public Q_SLOTS:
99105
/*: Title of Peers Table column which contains the peer's
100106
User Agent string. */
101107
tr("User Agent")};
102-
std::unique_ptr<PeerTablePriv> priv;
103108
QTimer *timer;
104109
};
105110

src/qt/rpcconsole.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_
727727

728728
// peer table signal handling - update peer details when selecting new node
729729
connect(ui->peerWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, &RPCConsole::updateDetailWidget);
730-
connect(model->getPeerTableModel(), &PeerTableModel::layoutChanged, this, &RPCConsole::updateDetailWidget);
730+
connect(model->getPeerTableModel(), &PeerTableModel::changed, this, &RPCConsole::updateDetailWidget);
731731

732732
// set up ban table
733733
ui->banlistWidget->setModel(model->getBanTableModel());

0 commit comments

Comments
 (0)