From d325799acdd8d010d5e4b2f77d9cc67d76d4ad28 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 24 Dec 2020 16:55:39 +0200 Subject: [PATCH] qt: Handle peer addition/removal in a right way This change fixes a bug when a multiple rows selection gets inconsistent after a peer addition/removal. --- src/qt/peertablemodel.cpp | 29 ++++++++++++++++++++++++++--- src/qt/peertablemodel.h | 3 +++ src/qt/rpcconsole.cpp | 2 +- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index a61b9f90b01..68ec45173ce 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -147,7 +147,30 @@ void PeerTableModel::refresh() new_peers_data.append(stats); } - Q_EMIT layoutAboutToBeChanged(); - m_peers_data.swap(new_peers_data); - Q_EMIT layoutChanged(); + // Handle a new peer addition or an old peer 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 + // We use the fact that interfaces::Node::getNodesStats + // returns std::vector naturally sorted by nodeid. + for (int i = 0; i < m_peers_data.size();) { + if (i < new_peers_data.size() && m_peers_data.at(i).nodeStats.nodeid == new_peers_data.at(i).nodeStats.nodeid) { + ++i; + continue; + } + // A peer has been removed from the table. + beginRemoveRows(QModelIndex(), i, i); + m_peers_data.erase(m_peers_data.begin() + i); + endRemoveRows(); + } + + if (m_peers_data.size() < new_peers_data.size()) { + // Some peers have been added to the end of the table. + beginInsertRows(QModelIndex(), m_peers_data.size(), new_peers_data.size() - 1); + m_peers_data.swap(new_peers_data); + endInsertRows(); + } else { + m_peers_data.swap(new_peers_data); + } + + Q_EMIT changed(); } diff --git a/src/qt/peertablemodel.h b/src/qt/peertablemodel.h index 2cf3f514720..3ebecc031ee 100644 --- a/src/qt/peertablemodel.h +++ b/src/qt/peertablemodel.h @@ -72,6 +72,9 @@ class PeerTableModel : public QAbstractTableModel public Q_SLOTS: void refresh(); +Q_SIGNALS: + void changed(); + private: //! Internal peer data structure. QList m_peers_data{}; diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 795db5baad2..98ae89bccf9 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -623,7 +623,7 @@ void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_ // peer table signal handling - update peer details when selecting new node connect(ui->peerWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, &RPCConsole::updateDetailWidget); - connect(model->getPeerTableModel(), &PeerTableModel::layoutChanged, this, &RPCConsole::updateDetailWidget); + connect(model->getPeerTableModel(), &PeerTableModel::changed, this, &RPCConsole::updateDetailWidget); // set up ban table ui->banlistWidget->setModel(model->getBanTableModel());