Merge bitcoin-core/gui#581: refactor: Revamp ClientModel code to handle core signals

bcbf982553 qt, doc: Remove unneeded comments (Hennadii Stepanov)
9bd1565f65 qt: Revamp ClientModel code to handle {Block|Header}Tip core signals (Hennadii Stepanov)
48f6d39659 qt: Revamp ClientModel code to handle BannedListChanged core signal (Hennadii Stepanov)
36b12af7ee qt: Revamp ClientModel code to handle AlertChanged core signal (Hennadii Stepanov)
bfe5140c50 qt: Revamp ClientModel code to handle NetworkActiveChanged core signal (Hennadii Stepanov)
639563d7fe qt: Revamp ClientModel code to handle NumConnectionsChanged core signal (Hennadii Stepanov)
508e2dca5e qt: Revamp ClientModel code to handle ShowProgress core signal (Hennadii Stepanov)

Pull request description:

  This PR:
  - is a pure refactoring with no behavior change
  - gets rid of `QMetaObject::invokeMethod()` "dynamic" calls, i.e., without compile-time checks of a called function name and its parameters
  - replaces `std::bind`s with lambdas, making parameter permutation (including parameter omitting) explicit
  - makes code simpler, more concise, and easier to reason about

  Additionally, debug messages have been unified.

ACKs for top commit:
  promag:
    Code review ACK bcbf982553
  w0xlt:
    tACK bcbf982553 on Ubuntu 21.10, Qt 5.15.2.

Tree-SHA512: 35f62b84f916b3ad7442f0fea945d344b3c448878b33506ac7b81fdf5e49bd2a82e12a6927dc91f62c335487bf2305cc45e2f08985303eef31c3ed2dd39e1037
This commit is contained in:
Hennadii Stepanov
2022-05-20 12:05:24 +02:00
2 changed files with 42 additions and 90 deletions

View File

@@ -21,9 +21,9 @@
#include <validation.h> #include <validation.h>
#include <stdint.h> #include <stdint.h>
#include <functional>
#include <QDebug> #include <QDebug>
#include <QMetaObject>
#include <QThread> #include <QThread>
#include <QTimer> #include <QTimer>
@@ -148,21 +148,6 @@ uint256 ClientModel::getBestBlockHash()
return m_cached_tip_blocks; return m_cached_tip_blocks;
} }
void ClientModel::updateNumConnections(int numConnections)
{
Q_EMIT numConnectionsChanged(numConnections);
}
void ClientModel::updateNetworkActive(bool networkActive)
{
Q_EMIT networkActiveChanged(networkActive);
}
void ClientModel::updateAlert()
{
Q_EMIT alertsChanged(getStatusBarWarnings());
}
enum BlockSource ClientModel::getBlockSource() const enum BlockSource ClientModel::getBlockSource() const
{ {
if (m_node.getReindex()) if (m_node.getReindex())
@@ -230,94 +215,65 @@ QString ClientModel::blocksDir() const
return GUIUtil::PathToQString(gArgs.GetBlocksDirPath()); return GUIUtil::PathToQString(gArgs.GetBlocksDirPath());
} }
void ClientModel::updateBanlist() void ClientModel::TipChanged(SynchronizationState sync_state, interfaces::BlockTip tip, double verification_progress, bool header)
{ {
banTableModel->refresh(); if (header) {
}
// Handlers for core signals
static void ShowProgress(ClientModel *clientmodel, const std::string &title, int nProgress)
{
// emits signal "showProgress"
bool invoked = QMetaObject::invokeMethod(clientmodel, "showProgress", Qt::QueuedConnection,
Q_ARG(QString, QString::fromStdString(title)),
Q_ARG(int, nProgress));
assert(invoked);
}
static void NotifyNumConnectionsChanged(ClientModel *clientmodel, int newNumConnections)
{
// Too noisy: qDebug() << "NotifyNumConnectionsChanged: " + QString::number(newNumConnections);
bool invoked = QMetaObject::invokeMethod(clientmodel, "updateNumConnections", Qt::QueuedConnection,
Q_ARG(int, newNumConnections));
assert(invoked);
}
static void NotifyNetworkActiveChanged(ClientModel *clientmodel, bool networkActive)
{
bool invoked = QMetaObject::invokeMethod(clientmodel, "updateNetworkActive", Qt::QueuedConnection,
Q_ARG(bool, networkActive));
assert(invoked);
}
static void NotifyAlertChanged(ClientModel *clientmodel)
{
qDebug() << "NotifyAlertChanged";
bool invoked = QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection);
assert(invoked);
}
static void BannedListChanged(ClientModel *clientmodel)
{
qDebug() << QString("%1: Requesting update for peer banlist").arg(__func__);
bool invoked = QMetaObject::invokeMethod(clientmodel, "updateBanlist", Qt::QueuedConnection);
assert(invoked);
}
static void BlockTipChanged(ClientModel* clientmodel, SynchronizationState sync_state, interfaces::BlockTip tip, double verificationProgress, bool fHeader)
{
if (fHeader) {
// cache best headers time and height to reduce future cs_main locks // cache best headers time and height to reduce future cs_main locks
clientmodel->cachedBestHeaderHeight = tip.block_height; cachedBestHeaderHeight = tip.block_height;
clientmodel->cachedBestHeaderTime = tip.block_time; cachedBestHeaderTime = tip.block_time;
} else { } else {
clientmodel->m_cached_num_blocks = tip.block_height; m_cached_num_blocks = tip.block_height;
WITH_LOCK(clientmodel->m_cached_tip_mutex, clientmodel->m_cached_tip_blocks = tip.block_hash;); WITH_LOCK(m_cached_tip_mutex, m_cached_tip_blocks = tip.block_hash;);
} }
// Throttle GUI notifications about (a) blocks during initial sync, and (b) both blocks and headers during reindex. // Throttle GUI notifications about (a) blocks during initial sync, and (b) both blocks and headers during reindex.
const bool throttle = (sync_state != SynchronizationState::POST_INIT && !fHeader) || sync_state == SynchronizationState::INIT_REINDEX; const bool throttle = (sync_state != SynchronizationState::POST_INIT && !header) || sync_state == SynchronizationState::INIT_REINDEX;
const int64_t now = throttle ? GetTimeMillis() : 0; const int64_t now = throttle ? GetTimeMillis() : 0;
int64_t& nLastUpdateNotification = fHeader ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification; int64_t& nLastUpdateNotification = header ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification;
if (throttle && now < nLastUpdateNotification + count_milliseconds(MODEL_UPDATE_DELAY)) { if (throttle && now < nLastUpdateNotification + count_milliseconds(MODEL_UPDATE_DELAY)) {
return; return;
} }
bool invoked = QMetaObject::invokeMethod(clientmodel, "numBlocksChanged", Qt::QueuedConnection, Q_EMIT numBlocksChanged(tip.block_height, QDateTime::fromSecsSinceEpoch(tip.block_time), verification_progress, header, sync_state);
Q_ARG(int, tip.block_height),
Q_ARG(QDateTime, QDateTime::fromSecsSinceEpoch(tip.block_time)),
Q_ARG(double, verificationProgress),
Q_ARG(bool, fHeader),
Q_ARG(SynchronizationState, sync_state));
assert(invoked);
nLastUpdateNotification = now; nLastUpdateNotification = now;
} }
void ClientModel::subscribeToCoreSignals() void ClientModel::subscribeToCoreSignals()
{ {
// Connect signals to client m_handler_show_progress = m_node.handleShowProgress(
m_handler_show_progress = m_node.handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2)); [this](const std::string& title, int progress, [[maybe_unused]] bool resume_possible) {
m_handler_notify_num_connections_changed = m_node.handleNotifyNumConnectionsChanged(std::bind(NotifyNumConnectionsChanged, this, std::placeholders::_1)); Q_EMIT showProgress(QString::fromStdString(title), progress);
m_handler_notify_network_active_changed = m_node.handleNotifyNetworkActiveChanged(std::bind(NotifyNetworkActiveChanged, this, std::placeholders::_1)); });
m_handler_notify_alert_changed = m_node.handleNotifyAlertChanged(std::bind(NotifyAlertChanged, this)); m_handler_notify_num_connections_changed = m_node.handleNotifyNumConnectionsChanged(
m_handler_banned_list_changed = m_node.handleBannedListChanged(std::bind(BannedListChanged, this)); [this](int new_num_connections) {
m_handler_notify_block_tip = m_node.handleNotifyBlockTip(std::bind(BlockTipChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, false)); Q_EMIT numConnectionsChanged(new_num_connections);
m_handler_notify_header_tip = m_node.handleNotifyHeaderTip(std::bind(BlockTipChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, true)); });
m_handler_notify_network_active_changed = m_node.handleNotifyNetworkActiveChanged(
[this](bool network_active) {
Q_EMIT networkActiveChanged(network_active);
});
m_handler_notify_alert_changed = m_node.handleNotifyAlertChanged(
[this]() {
qDebug() << "ClientModel: NotifyAlertChanged";
Q_EMIT alertsChanged(getStatusBarWarnings());
});
m_handler_banned_list_changed = m_node.handleBannedListChanged(
[this]() {
qDebug() << "ClienModel: Requesting update for peer banlist";
QMetaObject::invokeMethod(banTableModel, [this] { banTableModel->refresh(); });
});
m_handler_notify_block_tip = m_node.handleNotifyBlockTip(
[this](SynchronizationState sync_state, interfaces::BlockTip tip, double verification_progress) {
TipChanged(sync_state, tip, verification_progress, /*header=*/false);
});
m_handler_notify_header_tip = m_node.handleNotifyHeaderTip(
[this](SynchronizationState sync_state, interfaces::BlockTip tip, double verification_progress) {
TipChanged(sync_state, tip, verification_progress, /*header=*/true);
});
} }
void ClientModel::unsubscribeFromCoreSignals() void ClientModel::unsubscribeFromCoreSignals()
{ {
// Disconnect signals from client
m_handler_show_progress->disconnect(); m_handler_show_progress->disconnect();
m_handler_notify_num_connections_changed->disconnect(); m_handler_notify_num_connections_changed->disconnect();
m_handler_notify_network_active_changed->disconnect(); m_handler_notify_network_active_changed->disconnect();

View File

@@ -23,6 +23,7 @@ enum class SynchronizationState;
namespace interfaces { namespace interfaces {
class Handler; class Handler;
class Node; class Node;
struct BlockTip;
} }
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@@ -104,6 +105,7 @@ private:
//! A thread to interact with m_node asynchronously //! A thread to interact with m_node asynchronously
QThread* const m_thread; QThread* const m_thread;
void TipChanged(SynchronizationState sync_state, interfaces::BlockTip tip, double verification_progress, bool header);
void subscribeToCoreSignals(); void subscribeToCoreSignals();
void unsubscribeFromCoreSignals(); void unsubscribeFromCoreSignals();
@@ -120,12 +122,6 @@ Q_SIGNALS:
// Show progress dialog e.g. for verifychain // Show progress dialog e.g. for verifychain
void showProgress(const QString &title, int nProgress); void showProgress(const QString &title, int nProgress);
public Q_SLOTS:
void updateNumConnections(int numConnections);
void updateNetworkActive(bool networkActive);
void updateAlert();
void updateBanlist();
}; };
#endif // BITCOIN_QT_CLIENTMODEL_H #endif // BITCOIN_QT_CLIENTMODEL_H