Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move various state computations from the UI to the NodeModel #434

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
1 change: 0 additions & 1 deletion src/Makefile.qt.include
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,6 @@ QML_RES_QML = \
qml/controls/TextButton.qml \
qml/controls/Theme.qml \
qml/controls/ToggleButton.qml \
qml/controls/utils.js \
qml/controls/ValueInput.qml \
qml/pages/initerrormessage.qml \
qml/pages/main.qml \
Expand Down
1 change: 0 additions & 1 deletion src/qml/bitcoin_qml.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
<file>controls/TextButton.qml</file>
<file>controls/Theme.qml</file>
<file>controls/ToggleButton.qml</file>
<file>controls/utils.js</file>
<file>controls/ValueInput.qml</file>
<file>pages/initerrormessage.qml</file>
<file>pages/main.qml</file>
Expand Down
27 changes: 6 additions & 21 deletions src/qml/components/BlockClock.qml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import Qt.labs.settings 1.0
import org.bitcoincore.qt 1.0

import "../controls"
import "../controls/utils.js" as Utils

Item {
id: root
Expand All @@ -25,13 +24,12 @@ Item {
property alias headerSize: mainText.font.pixelSize
property alias subText: subText.text
property int headerSize: 32
property bool connected: nodeModel.numOutboundPeers > 0
property bool synced: nodeModel.verificationProgress > 0.999
property string syncProgress: formatProgressPercentage(nodeModel.verificationProgress * 100)
property bool connected: nodeModel.connected
property bool synced: nodeModel.synced
property string syncProgress: nodeModel.formattedVerificationProgress
property bool paused: false
property var syncState: Utils.formatRemainingSyncTime(nodeModel.remainingSyncTime)
property string syncTime: syncState.text
property bool estimating: syncState.estimating
property string syncTime: nodeModel.formattedRemainingSyncTime
property bool estimating: nodeModel.estimatingSyncTime
property bool faulted: nodeModel.faulted

activeFocusOnTab: true
Expand All @@ -53,7 +51,7 @@ Item {
verificationProgress: nodeModel.verificationProgress
paused: root.paused || root.faulted
connected: root.connected
synced: nodeModel.verificationProgress > 0.999
synced: root.synced
backgroundColor: Theme.color.neutral2
timeTickColor: Theme.color.neutral5
confirmationColors: Theme.color.confirmationColors
Expand Down Expand Up @@ -242,17 +240,4 @@ Item {
}
}
]


function formatProgressPercentage(progress) {
if (progress >= 1) {
return Math.round(progress) + "%"
} else if (progress >= 0.1) {
return progress.toFixed(1) + "%"
} else if (progress >= 0.01) {
return progress.toFixed(2) + "%"
} else {
return "0%"
}
}
}
66 changes: 0 additions & 66 deletions src/qml/controls/utils.js

This file was deleted.

115 changes: 115 additions & 0 deletions src/qml/models/nodemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,32 @@ void NodeModel::setNumOutboundPeers(int new_num)
{
if (new_num != m_num_outbound_peers) {
m_num_outbound_peers = new_num;

bool new_connected = (m_num_outbound_peers > 0);
if (new_connected != m_connected) {
setConnected(new_connected);
}

Q_EMIT numOutboundPeersChanged();
}
}

void NodeModel::setConnected(bool new_connected)
{
if (new_connected != m_connected) {
m_connected = new_connected;
Q_EMIT connectedChanged();
}
}

void NodeModel::setEstimatingSyncTime(bool new_estimating)
{
if (m_estimating_sync_time != new_estimating) {
m_estimating_sync_time = new_estimating;
Q_EMIT estimatingSyncTimeChanged();
}
}

void NodeModel::setRemainingSyncTime(double new_progress)
{
int currentTime = QDateTime::currentDateTime().toMSecsSinceEpoch();
Expand All @@ -66,25 +88,118 @@ void NodeModel::setRemainingSyncTime(double new_progress)
}
if (remainingMSecs > 0 && m_block_process_time.count() % 1000 == 0) {
m_remaining_sync_time = remainingMSecs;
setFormattedRemainingSyncTime(m_remaining_sync_time);

Q_EMIT remainingSyncTimeChanged();
}
static const int MAX_SAMPLES = 5000;
if (m_block_process_time.count() > MAX_SAMPLES) {
m_block_process_time.remove(1, m_block_process_time.count() - 1);
}
} else {
m_remaining_sync_time = 0;
setFormattedRemainingSyncTime(m_remaining_sync_time);

Q_EMIT remainingSyncTimeChanged();
}
}

void NodeModel::setFormattedRemainingSyncTime(int new_time)
{
int minutes = new_time / 60000;
int seconds = (new_time % 60000) / 1000;

int weeks = minutes / 10080;
minutes %= 10080;

int days = minutes / 1440;
minutes %= 1440;

int hours = minutes / 60;
minutes %= 60;

if (weeks > 0) {
m_formatted_remaining_sync_time = QObject::tr("~%1 %2 left")
.arg(weeks)
.arg(weeks == 1 ? QObject::tr("week") : QObject::tr("weeks"));
setEstimatingSyncTime(false);
} else if (days > 0) {
m_formatted_remaining_sync_time = QObject::tr("~%1 %2 left")
.arg(days)
.arg(days == 1 ? QObject::tr("day") : QObject::tr("days"));
setEstimatingSyncTime(false);
} else if (hours >= 5) {
m_formatted_remaining_sync_time = QObject::tr("~%1 %2 left")
.arg(hours)
.arg(hours == 1 ? QObject::tr("hour") : QObject::tr("hours"));
setEstimatingSyncTime(false);
} else if (hours > 0) {
m_formatted_remaining_sync_time = QObject::tr("~%1h %2m left")
.arg(hours)
.arg(minutes);
setEstimatingSyncTime(false);
} else if (minutes >= 5) {
m_formatted_remaining_sync_time = QObject::tr("~%1 %2 left")
.arg(minutes)
.arg(minutes == 1 ? QObject::tr("minute") : QObject::tr("minutes"));
setEstimatingSyncTime(false);
} else if (minutes > 0) {
m_formatted_remaining_sync_time = QObject::tr("~%1m %2s left")
.arg(minutes)
.arg(seconds);
setEstimatingSyncTime(false);
} else if (seconds > 0) {
m_formatted_remaining_sync_time = QObject::tr("~%1 %2 left")
.arg(seconds)
.arg(seconds == 1 ? QObject::tr("second") : QObject::tr("seconds"));
setEstimatingSyncTime(false);
} else {
if (m_synced) {
setEstimatingSyncTime(false);
} else {
m_formatted_remaining_sync_time = QObject::tr("Estimating");
setEstimatingSyncTime(true);
}
}
}

void NodeModel::setVerificationProgress(double new_progress)
{
if (new_progress != m_verification_progress) {
setRemainingSyncTime(new_progress);
setFormattedVerificationProgress(new_progress);

if (new_progress >= 0.999) {
setSynced(true);
}

m_verification_progress = new_progress;
Q_EMIT verificationProgressChanged();
}
}

void NodeModel::setFormattedVerificationProgress(double new_progress)
{
double percentage = new_progress * 100.00;

if (percentage >= 99.99) {
m_formatted_verification_progress = QStringLiteral("100%");
} else if (percentage == 0.0) {
m_formatted_verification_progress = QStringLiteral("0%");
} else {
int decimal_places = (percentage >= 10.0) ? 1 : 2;
m_formatted_verification_progress = QString::number(percentage, 'f', decimal_places) + '%';
}
}

void NodeModel::setSynced(bool new_synced)
{
if (m_synced != new_synced) {
m_synced = new_synced;
Q_EMIT syncedChanged();
}
}

void NodeModel::setPause(bool new_pause)
{
if(m_pause != new_pause) {
Expand Down
24 changes: 24 additions & 0 deletions src/qml/models/nodemodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,13 @@ class NodeModel : public QObject
Q_PROPERTY(QString fullClientVersion READ fullClientVersion CONSTANT)
Q_PROPERTY(int numOutboundPeers READ numOutboundPeers NOTIFY numOutboundPeersChanged)
Q_PROPERTY(int maxNumOutboundPeers READ maxNumOutboundPeers CONSTANT)
Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged)
Q_PROPERTY(int remainingSyncTime READ remainingSyncTime NOTIFY remainingSyncTimeChanged)
Q_PROPERTY(QString formattedRemainingSyncTime READ formattedRemainingSyncTime NOTIFY remainingSyncTimeChanged)
Q_PROPERTY(bool estimatingSyncTime READ estimatingSyncTime NOTIFY estimatingSyncTimeChanged)
Q_PROPERTY(double verificationProgress READ verificationProgress NOTIFY verificationProgressChanged)
Q_PROPERTY(QString formattedVerificationProgress READ formattedVerificationProgress NOTIFY verificationProgressChanged)
Q_PROPERTY(bool synced READ synced NOTIFY syncedChanged)
Q_PROPERTY(bool pause READ pause WRITE setPause NOTIFY pauseChanged)
Q_PROPERTY(bool faulted READ errorState WRITE setErrorState NOTIFY errorStateChanged)

Expand All @@ -44,10 +49,15 @@ class NodeModel : public QObject
int numOutboundPeers() const { return m_num_outbound_peers; }
void setNumOutboundPeers(int new_num);
int maxNumOutboundPeers() const { return m_max_num_outbound_peers; }
bool connected() const { return m_connected; }
int remainingSyncTime() const { return m_remaining_sync_time; }
void setRemainingSyncTime(double new_progress);
QString formattedRemainingSyncTime() const { return m_formatted_remaining_sync_time; }
bool estimatingSyncTime() const { return m_estimating_sync_time; }
double verificationProgress() const { return m_verification_progress; }
void setVerificationProgress(double new_progress);
QString formattedVerificationProgress() const { return m_formatted_verification_progress; }
bool synced() const { return m_synced; }
bool pause() const { return m_pause; }
void setPause(bool new_pause);
bool errorState() const { return m_faulted; }
Expand All @@ -68,10 +78,13 @@ public Q_SLOTS:
Q_SIGNALS:
void blockTipHeightChanged();
void numOutboundPeersChanged();
void connectedChanged();
void remainingSyncTimeChanged();
void estimatingSyncTimeChanged();
void requestedInitialize();
void requestedShutdown();
void verificationProgressChanged();
void syncedChanged();
void pauseChanged(bool new_pause);
void errorStateChanged(bool new_error_state);

Expand All @@ -82,12 +95,23 @@ public Q_SLOTS:
void timerEvent(QTimerEvent* event) override;

private:
void setConnected(bool new_connected);
void setEstimatingSyncTime(bool new_estimating);
void setFormattedRemainingSyncTime(int new_time);
void setFormattedVerificationProgress(double new_progress);
void setSynced(bool new_synced);

// Properties that are exposed to QML.
int m_block_tip_height{0};
int m_num_outbound_peers{0};
bool m_connected{false};
static constexpr int m_max_num_outbound_peers{MAX_OUTBOUND_FULL_RELAY_CONNECTIONS + MAX_BLOCK_RELAY_ONLY_CONNECTIONS};
int m_remaining_sync_time{0};
QString m_formatted_remaining_sync_time;
bool m_estimating_sync_time{false};
double m_verification_progress{0.0};
QString m_formatted_verification_progress;
bool m_synced{false};
bool m_pause{false};
bool m_faulted{false};

Expand Down
9 changes: 4 additions & 5 deletions src/qml/pages/wallet/DesktopWallets.qml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import QtQuick.Layouts 1.15
import org.bitcoincore.qt 1.0

import "../../controls"
import "../../controls/utils.js" as Utils
import "../../components"
import "../node"

Expand Down Expand Up @@ -77,10 +76,10 @@ Page {

Tooltip {
id: blockClockTooltip
property var syncState: Utils.formatRemainingSyncTime(nodeModel.remainingSyncTime)
property bool synced: nodeModel.verificationProgress > 0.9999
property string remainingSyncTime: nodeModel.formattedRemainingSyncTime
property bool synced: nodeModel.synced
property bool paused: nodeModel.pause
property bool connected: nodeModel.numOutboundPeers > 0
property bool connected: nodeModel.connected

anchors.top: blockClockTabButton.bottom
anchors.topMargin: -5
Expand All @@ -93,7 +92,7 @@ Page {
} else if (connected && synced) {
qsTr("Blocktime\n" + Number(nodeModel.blockTipHeight).toLocaleString(Qt.locale(), 'f', 0))
} else if (connected){
qsTr("Downloading blocks\n" + syncState.text)
qsTr("Downloading blocks\n" + blockClockTooltip.remainingSyncTime)
} else {
qsTr("Connecting")
}
Expand Down
Loading