Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 40 additions & 84 deletions src/qt/clientmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
#include <validation.h>

#include <stdint.h>
#include <functional>

#include <QDebug>
#include <QMetaObject>
#include <QThread>
#include <QTimer>

Expand Down Expand Up @@ -148,21 +148,6 @@ uint256 ClientModel::getBestBlockHash()
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
{
if (m_node.getReindex())
Expand Down Expand Up @@ -230,94 +215,65 @@ QString ClientModel::blocksDir() const
return GUIUtil::PathToQString(gArgs.GetBlocksDirPath());
}

void ClientModel::updateBanlist()
{
banTableModel->refresh();
}

// 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)
void ClientModel::TipChanged(SynchronizationState sync_state, interfaces::BlockTip tip, double verification_progress, bool header)
{
if (fHeader) {
if (header) {
// cache best headers time and height to reduce future cs_main locks
clientmodel->cachedBestHeaderHeight = tip.block_height;
clientmodel->cachedBestHeaderTime = tip.block_time;
cachedBestHeaderHeight = tip.block_height;
cachedBestHeaderTime = tip.block_time;
} else {
clientmodel->m_cached_num_blocks = tip.block_height;
WITH_LOCK(clientmodel->m_cached_tip_mutex, clientmodel->m_cached_tip_blocks = tip.block_hash;);
m_cached_num_blocks = tip.block_height;
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.
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;
int64_t& nLastUpdateNotification = fHeader ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification;
int64_t& nLastUpdateNotification = header ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification;
if (throttle && now < nLastUpdateNotification + count_milliseconds(MODEL_UPDATE_DELAY)) {
return;
}

bool invoked = QMetaObject::invokeMethod(clientmodel, "numBlocksChanged", Qt::QueuedConnection,
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);
Q_EMIT numBlocksChanged(tip.block_height, QDateTime::fromSecsSinceEpoch(tip.block_time), verification_progress, header, sync_state);
nLastUpdateNotification = now;
}

void ClientModel::subscribeToCoreSignals()
{
// Connect signals to client
m_handler_show_progress = m_node.handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2));
m_handler_notify_num_connections_changed = m_node.handleNotifyNumConnectionsChanged(std::bind(NotifyNumConnectionsChanged, this, std::placeholders::_1));
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_banned_list_changed = m_node.handleBannedListChanged(std::bind(BannedListChanged, this));
m_handler_notify_block_tip = m_node.handleNotifyBlockTip(std::bind(BlockTipChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, false));
m_handler_notify_header_tip = m_node.handleNotifyHeaderTip(std::bind(BlockTipChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, true));
m_handler_show_progress = m_node.handleShowProgress(
[this](const std::string& title, int progress, [[maybe_unused]] bool resume_possible) {
Q_EMIT showProgress(QString::fromStdString(title), progress);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

508e2dc

This is fine because auto connection is used:

connect(_clientModel, &ClientModel::showProgress, this, &BitcoinGUI::showProgress);

});
m_handler_notify_num_connections_changed = m_node.handleNotifyNumConnectionsChanged(
[this](int new_num_connections) {
Q_EMIT numConnectionsChanged(new_num_connections);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

639563d

Also fine:

connect(_clientModel, &ClientModel::numConnectionsChanged, this, &BitcoinGUI::setNumConnections);

connect(model, &ClientModel::numConnectionsChanged, this, &RPCConsole::setNumConnections);

});
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()
{
// Disconnect signals from client
m_handler_show_progress->disconnect();
m_handler_notify_num_connections_changed->disconnect();
m_handler_notify_network_active_changed->disconnect();
Expand Down
8 changes: 2 additions & 6 deletions src/qt/clientmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ enum class SynchronizationState;
namespace interfaces {
class Handler;
class Node;
struct BlockTip;
}

QT_BEGIN_NAMESPACE
Expand Down Expand Up @@ -104,6 +105,7 @@ class ClientModel : public QObject
//! A thread to interact with m_node asynchronously
QThread* const m_thread;

void TipChanged(SynchronizationState sync_state, interfaces::BlockTip tip, double verification_progress, bool header);
void subscribeToCoreSignals();
void unsubscribeFromCoreSignals();

Expand All @@ -120,12 +122,6 @@ class ClientModel : public QObject

// Show progress dialog e.g. for verifychain
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