From e35e4b2ba052c9a533626286026dbe0a2d546c5b Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 12 Nov 2019 13:23:09 +0200 Subject: util: Add PruneMiBtoGB() function Now the text of prune QCheckBox shows the space in GB instead of thousands MiB, which is consistent with other parts of the GUI. --- src/qt/intro.cpp | 17 +++++++++-------- src/qt/optionsmodel.h | 6 ++++++ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index f064556ae5..183c2fcfb6 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -23,7 +24,7 @@ #include /* Total required space (in GB) depending on user choice (prune, not prune) */ -static uint64_t requiredSpace; +static int64_t requiredSpace; /* Check free space asynchronously to prevent hanging the UI thread. @@ -130,18 +131,18 @@ Intro::Intro(QWidget *parent, uint64_t blockchain_size, uint64_t chain_state_siz ); ui->lblExplanation2->setText(ui->lblExplanation2->text().arg(PACKAGE_NAME)); - uint64_t pruneTarget = std::max(0, gArgs.GetArg("-prune", 0)); - if (pruneTarget > 1) { // -prune=1 means enabled, above that it's a size in MB + int64_t prune_target_mib = std::max(0, gArgs.GetArg("-prune", 0)); + if (prune_target_mib > 1) { // -prune=1 means enabled, above that it's a size in MiB ui->prune->setChecked(true); ui->prune->setEnabled(false); } - ui->prune->setText(tr("Discard blocks after verification, except most recent %1 GB (prune)").arg(pruneTarget ? pruneTarget / 1000 : DEFAULT_PRUNE_TARGET_GB)); + const int prune_target_gb = PruneMiBtoGB(prune_target_mib); + ui->prune->setText(tr("Discard blocks after verification, except most recent %1 GB (prune)").arg(prune_target_gb ? prune_target_gb : DEFAULT_PRUNE_TARGET_GB)); requiredSpace = m_blockchain_size; QString storageRequiresMsg = tr("At least %1 GB of data will be stored in this directory, and it will grow over time."); - if (pruneTarget) { - uint64_t prunedGBs = std::ceil(pruneTarget * 1024 * 1024.0 / GB_BYTES); - if (prunedGBs <= requiredSpace) { - requiredSpace = prunedGBs; + if (prune_target_gb) { + if (prune_target_gb <= requiredSpace) { + requiredSpace = prune_target_gb; storageRequiresMsg = tr("Approximately %1 GB of data will be stored in this directory."); } ui->lblExplanation3->setVisible(true); diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 6f5c8b8c5c..9751deadc4 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -6,6 +6,7 @@ #define BITCOIN_QT_OPTIONSMODEL_H #include +#include #include @@ -16,6 +17,11 @@ class Node; extern const char *DEFAULT_GUI_PROXY_HOST; static constexpr unsigned short DEFAULT_GUI_PROXY_PORT = 9050; +/** + * Convert configured prune target MiB to displayed GB. Round up to avoid underestimating max disk usage. + */ +static inline int PruneMiBtoGB(int64_t mib) { return (mib * 1024 * 1024 + GB_BYTES - 1) / GB_BYTES; } + /** Interface from Qt to configuration data structure for Bitcoin client. To Qt, the options are presented as a list with the different options laid out vertically. -- cgit v1.2.3 From 2bede28cd9ec638d8bb32c187ccf12d89345218e Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 12 Nov 2019 12:14:52 +0200 Subject: util: Add PruneGBtoMiB() function This commit does not change behavior. --- src/qt/optionsmodel.cpp | 5 ++--- src/qt/optionsmodel.h | 5 +++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index df5248f55e..f8cbd8358a 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -240,9 +240,8 @@ void OptionsModel::SetPruneEnabled(bool prune, bool force) { QSettings settings; settings.setValue("bPrune", prune); - // Convert prune size from GB to MiB: - const uint64_t nPruneSizeMiB = (settings.value("nPruneSize").toInt() * GB_BYTES) >> 20; - std::string prune_val = prune ? std::to_string(nPruneSizeMiB) : "0"; + const int64_t prune_target_mib = PruneGBtoMiB(settings.value("nPruneSize").toInt()); + std::string prune_val = prune ? std::to_string(prune_target_mib) : "0"; if (force) { m_node.forceSetArg("-prune", prune_val); return; diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 9751deadc4..81ab0008e4 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -22,6 +22,11 @@ static constexpr unsigned short DEFAULT_GUI_PROXY_PORT = 9050; */ static inline int PruneMiBtoGB(int64_t mib) { return (mib * 1024 * 1024 + GB_BYTES - 1) / GB_BYTES; } +/** + * Convert displayed prune target GB to configured MiB. Round down so roundtrip GB -> MiB -> GB conversion is stable. + */ +static inline int64_t PruneGBtoMiB(int gb) { return gb * GB_BYTES / 1024 / 1024; } + /** Interface from Qt to configuration data structure for Bitcoin client. To Qt, the options are presented as a list with the different options laid out vertically. -- cgit v1.2.3 From e4caa82a03df5c6a6d5d29f34ab006d732c6dac1 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 12 Nov 2019 14:25:43 +0200 Subject: refactor: Replace static variable with data member --- src/qt/intro.cpp | 37 ++++++++++++++----------------------- src/qt/intro.h | 8 +++++--- 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 183c2fcfb6..196f4b50bc 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -23,9 +23,6 @@ #include -/* Total required space (in GB) depending on user choice (prune, not prune) */ -static int64_t requiredSpace; - /* Check free space asynchronously to prevent hanging the UI thread. Up to one request to check a path is in flight to this thread; when the check() @@ -111,13 +108,13 @@ void FreespaceChecker::check() } -Intro::Intro(QWidget *parent, uint64_t blockchain_size, uint64_t chain_state_size) : +Intro::Intro(QWidget *parent, int64_t blockchain_size_gb, int64_t chain_state_size_gb) : QDialog(parent), ui(new Ui::Intro), thread(nullptr), signalled(false), - m_blockchain_size(blockchain_size), - m_chain_state_size(chain_state_size) + m_blockchain_size_gb(blockchain_size_gb), + m_chain_state_size_gb(chain_state_size_gb) { ui->setupUi(this); ui->welcomeLabel->setText(ui->welcomeLabel->text().arg(PACKAGE_NAME)); @@ -125,7 +122,7 @@ Intro::Intro(QWidget *parent, uint64_t blockchain_size, uint64_t chain_state_siz ui->lblExplanation1->setText(ui->lblExplanation1->text() .arg(PACKAGE_NAME) - .arg(m_blockchain_size) + .arg(m_blockchain_size_gb) .arg(2009) .arg(tr("Bitcoin")) ); @@ -138,21 +135,16 @@ Intro::Intro(QWidget *parent, uint64_t blockchain_size, uint64_t chain_state_siz } const int prune_target_gb = PruneMiBtoGB(prune_target_mib); ui->prune->setText(tr("Discard blocks after verification, except most recent %1 GB (prune)").arg(prune_target_gb ? prune_target_gb : DEFAULT_PRUNE_TARGET_GB)); - requiredSpace = m_blockchain_size; + m_required_space_gb = m_blockchain_size_gb + m_chain_state_size_gb; QString storageRequiresMsg = tr("At least %1 GB of data will be stored in this directory, and it will grow over time."); - if (prune_target_gb) { - if (prune_target_gb <= requiredSpace) { - requiredSpace = prune_target_gb; - storageRequiresMsg = tr("Approximately %1 GB of data will be stored in this directory."); - } - ui->lblExplanation3->setVisible(true); - } else { - ui->lblExplanation3->setVisible(false); + if (0 < prune_target_gb && prune_target_gb <= m_blockchain_size_gb) { + m_required_space_gb = prune_target_gb + m_chain_state_size_gb; + storageRequiresMsg = tr("Approximately %1 GB of data will be stored in this directory."); } - requiredSpace += m_chain_state_size; + ui->lblExplanation3->setVisible(prune_target_gb > 0); ui->sizeWarningLabel->setText( tr("%1 will download and store a copy of the Bitcoin block chain.").arg(PACKAGE_NAME) + " " + - storageRequiresMsg.arg(requiredSpace) + " " + + storageRequiresMsg.arg(m_required_space_gb) + " " + tr("The wallet will also be stored in this directory.") ); this->adjustSize(); @@ -272,13 +264,12 @@ void Intro::setStatus(int status, const QString &message, quint64 bytesAvailable ui->freeSpace->setText(""); } else { QString freeString = tr("%n GB of free space available", "", bytesAvailable/GB_BYTES); - if(bytesAvailable < requiredSpace * GB_BYTES) - { - freeString += " " + tr("(of %n GB needed)", "", requiredSpace); + if (bytesAvailable < m_required_space_gb * GB_BYTES) { + freeString += " " + tr("(of %n GB needed)", "", m_required_space_gb); ui->freeSpace->setStyleSheet("QLabel { color: #800000 }"); ui->prune->setChecked(true); - } else if (bytesAvailable / GB_BYTES - requiredSpace < 10) { - freeString += " " + tr("(%n GB needed for full chain)", "", requiredSpace); + } else if (bytesAvailable / GB_BYTES - m_required_space_gb < 10) { + freeString += " " + tr("(%n GB needed for full chain)", "", m_required_space_gb); ui->freeSpace->setStyleSheet("QLabel { color: #999900 }"); ui->prune->setChecked(true); } else { diff --git a/src/qt/intro.h b/src/qt/intro.h index 41da06141f..157b33b456 100644 --- a/src/qt/intro.h +++ b/src/qt/intro.h @@ -31,7 +31,7 @@ class Intro : public QDialog public: explicit Intro(QWidget *parent = nullptr, - uint64_t blockchain_size = 0, uint64_t chain_state_size = 0); + int64_t blockchain_size_gb = 0, int64_t chain_state_size_gb = 0); ~Intro(); QString getDataDirectory(); @@ -67,8 +67,10 @@ private: QMutex mutex; bool signalled; QString pathToCheck; - uint64_t m_blockchain_size; - uint64_t m_chain_state_size; + const int64_t m_blockchain_size_gb; + const int64_t m_chain_state_size_gb; + //! Total required space (in GB) depending on user choice (prune or not prune). + int64_t m_required_space_gb{0}; void startThread(); void checkPath(const QString &dataDir); -- cgit v1.2.3 From daa3f3fa9071a229275dd6a1b8445237ddc3fa97 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 12 Nov 2019 15:21:20 +0200 Subject: refactor: Add Intro::UpdatePruneLabels() This is a move-only commit and it does not change behavior. --- src/qt/intro.cpp | 31 ++++++++++++++++++------------- src/qt/intro.h | 1 + 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 196f4b50bc..a1a7c8ab8b 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -135,19 +135,7 @@ Intro::Intro(QWidget *parent, int64_t blockchain_size_gb, int64_t chain_state_si } const int prune_target_gb = PruneMiBtoGB(prune_target_mib); ui->prune->setText(tr("Discard blocks after verification, except most recent %1 GB (prune)").arg(prune_target_gb ? prune_target_gb : DEFAULT_PRUNE_TARGET_GB)); - m_required_space_gb = m_blockchain_size_gb + m_chain_state_size_gb; - QString storageRequiresMsg = tr("At least %1 GB of data will be stored in this directory, and it will grow over time."); - if (0 < prune_target_gb && prune_target_gb <= m_blockchain_size_gb) { - m_required_space_gb = prune_target_gb + m_chain_state_size_gb; - storageRequiresMsg = tr("Approximately %1 GB of data will be stored in this directory."); - } - ui->lblExplanation3->setVisible(prune_target_gb > 0); - ui->sizeWarningLabel->setText( - tr("%1 will download and store a copy of the Bitcoin block chain.").arg(PACKAGE_NAME) + " " + - storageRequiresMsg.arg(m_required_space_gb) + " " + - tr("The wallet will also be stored in this directory.") - ); - this->adjustSize(); + UpdatePruneLabels(prune_target_gb); startThread(); } @@ -341,3 +329,20 @@ QString Intro::getPathToCheck() mutex.unlock(); return retval; } + +void Intro::UpdatePruneLabels(int64_t prune_target_gb) +{ + m_required_space_gb = m_blockchain_size_gb + m_chain_state_size_gb; + QString storageRequiresMsg = tr("At least %1 GB of data will be stored in this directory, and it will grow over time."); + if (0 < prune_target_gb && prune_target_gb <= m_blockchain_size_gb) { + m_required_space_gb = prune_target_gb + m_chain_state_size_gb; + storageRequiresMsg = tr("Approximately %1 GB of data will be stored in this directory."); + } + ui->lblExplanation3->setVisible(prune_target_gb > 0); + ui->sizeWarningLabel->setText( + tr("%1 will download and store a copy of the Bitcoin block chain.").arg(PACKAGE_NAME) + " " + + storageRequiresMsg.arg(m_required_space_gb) + " " + + tr("The wallet will also be stored in this directory.") + ); + this->adjustSize(); +} diff --git a/src/qt/intro.h b/src/qt/intro.h index 157b33b456..b4fd390006 100644 --- a/src/qt/intro.h +++ b/src/qt/intro.h @@ -75,6 +75,7 @@ private: void startThread(); void checkPath(const QString &dataDir); QString getPathToCheck(); + void UpdatePruneLabels(int64_t prune_target_gb); friend class FreespaceChecker; }; -- cgit v1.2.3 From 4824a7d36cf47e766865e0fefe952ec860eb82dd Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 8 Dec 2019 17:18:15 +0200 Subject: gui: Add Intro::UpdateFreeSpaceLabel() If a new custom datadir has enough free space, the prune checkbox gets unchecked, unless -prune=NNN command-line option is provided. --- src/qt/intro.cpp | 31 +++++++++++++++++++------------ src/qt/intro.h | 2 ++ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index a1a7c8ab8b..cb7b13260a 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -251,24 +251,31 @@ void Intro::setStatus(int status, const QString &message, quint64 bytesAvailable { ui->freeSpace->setText(""); } else { - QString freeString = tr("%n GB of free space available", "", bytesAvailable/GB_BYTES); - if (bytesAvailable < m_required_space_gb * GB_BYTES) { - freeString += " " + tr("(of %n GB needed)", "", m_required_space_gb); - ui->freeSpace->setStyleSheet("QLabel { color: #800000 }"); - ui->prune->setChecked(true); - } else if (bytesAvailable / GB_BYTES - m_required_space_gb < 10) { - freeString += " " + tr("(%n GB needed for full chain)", "", m_required_space_gb); - ui->freeSpace->setStyleSheet("QLabel { color: #999900 }"); - ui->prune->setChecked(true); - } else { - ui->freeSpace->setStyleSheet(""); + m_bytes_available = bytesAvailable; + if (ui->prune->isEnabled()) { + ui->prune->setChecked(m_bytes_available < (m_blockchain_size_gb + m_chain_state_size_gb + 10) * GB_BYTES); } - ui->freeSpace->setText(freeString + "."); + UpdateFreeSpaceLabel(); } /* Don't allow confirm in ERROR state */ ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(status != FreespaceChecker::ST_ERROR); } +void Intro::UpdateFreeSpaceLabel() +{ + QString freeString = tr("%n GB of free space available", "", m_bytes_available / GB_BYTES); + if (m_bytes_available < m_required_space_gb * GB_BYTES) { + freeString += " " + tr("(of %n GB needed)", "", m_required_space_gb); + ui->freeSpace->setStyleSheet("QLabel { color: #800000 }"); + } else if (m_bytes_available / GB_BYTES - m_required_space_gb < 10) { + freeString += " " + tr("(%n GB needed for full chain)", "", m_required_space_gb); + ui->freeSpace->setStyleSheet("QLabel { color: #999900 }"); + } else { + ui->freeSpace->setStyleSheet(""); + } + ui->freeSpace->setText(freeString + "."); +} + void Intro::on_dataDirectory_textChanged(const QString &dataDirStr) { /* Disable OK button until check result comes in */ diff --git a/src/qt/intro.h b/src/qt/intro.h index b4fd390006..8375847cc0 100644 --- a/src/qt/intro.h +++ b/src/qt/intro.h @@ -71,11 +71,13 @@ private: const int64_t m_chain_state_size_gb; //! Total required space (in GB) depending on user choice (prune or not prune). int64_t m_required_space_gb{0}; + uint64_t m_bytes_available{0}; void startThread(); void checkPath(const QString &dataDir); QString getPathToCheck(); void UpdatePruneLabels(int64_t prune_target_gb); + void UpdateFreeSpaceLabel(); friend class FreespaceChecker; }; -- cgit v1.2.3 From 4f7127d1e3a51f0f55d42a08439c516dcc8d1a26 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 8 Dec 2019 23:28:50 +0200 Subject: gui: Make Intro consistent with prune checkbox When prune checkbox is toggled, the related text labels and the amount of required space shown are updated (previously they were only updated when the data directory was updated). --- src/qt/intro.cpp | 34 ++++++++++++++++++++++++---------- src/qt/intro.h | 3 ++- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index cb7b13260a..873d9dcd6f 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -107,6 +107,15 @@ void FreespaceChecker::check() Q_EMIT reply(replyStatus, replyMessage, freeBytesAvailable); } +namespace { +//! Return pruning size that will be used if automatic pruning is enabled. +int GetPruneTargetGB() +{ + int64_t prune_target_mib = gArgs.GetArg("-prune", 0); + // >1 means automatic pruning is enabled by config, 1 means manual pruning, 0 means no pruning. + return prune_target_mib > 1 ? PruneMiBtoGB(prune_target_mib) : DEFAULT_PRUNE_TARGET_GB; +} +} // namespace Intro::Intro(QWidget *parent, int64_t blockchain_size_gb, int64_t chain_state_size_gb) : QDialog(parent), @@ -114,7 +123,8 @@ Intro::Intro(QWidget *parent, int64_t blockchain_size_gb, int64_t chain_state_si thread(nullptr), signalled(false), m_blockchain_size_gb(blockchain_size_gb), - m_chain_state_size_gb(chain_state_size_gb) + m_chain_state_size_gb(chain_state_size_gb), + m_prune_target_gb{GetPruneTargetGB()} { ui->setupUi(this); ui->welcomeLabel->setText(ui->welcomeLabel->text().arg(PACKAGE_NAME)); @@ -128,14 +138,18 @@ Intro::Intro(QWidget *parent, int64_t blockchain_size_gb, int64_t chain_state_si ); ui->lblExplanation2->setText(ui->lblExplanation2->text().arg(PACKAGE_NAME)); - int64_t prune_target_mib = std::max(0, gArgs.GetArg("-prune", 0)); - if (prune_target_mib > 1) { // -prune=1 means enabled, above that it's a size in MiB + if (gArgs.GetArg("-prune", 0) > 1) { // -prune=1 means enabled, above that it's a size in MiB ui->prune->setChecked(true); ui->prune->setEnabled(false); } - const int prune_target_gb = PruneMiBtoGB(prune_target_mib); - ui->prune->setText(tr("Discard blocks after verification, except most recent %1 GB (prune)").arg(prune_target_gb ? prune_target_gb : DEFAULT_PRUNE_TARGET_GB)); - UpdatePruneLabels(prune_target_gb); + ui->prune->setText(tr("Discard blocks after verification, except most recent %1 GB (prune)").arg(m_prune_target_gb)); + UpdatePruneLabels(ui->prune->isChecked()); + + connect(ui->prune, &QCheckBox::toggled, [this](bool prune_checked) { + UpdatePruneLabels(prune_checked); + UpdateFreeSpaceLabel(); + }); + startThread(); } @@ -337,15 +351,15 @@ QString Intro::getPathToCheck() return retval; } -void Intro::UpdatePruneLabels(int64_t prune_target_gb) +void Intro::UpdatePruneLabels(bool prune_checked) { m_required_space_gb = m_blockchain_size_gb + m_chain_state_size_gb; QString storageRequiresMsg = tr("At least %1 GB of data will be stored in this directory, and it will grow over time."); - if (0 < prune_target_gb && prune_target_gb <= m_blockchain_size_gb) { - m_required_space_gb = prune_target_gb + m_chain_state_size_gb; + if (prune_checked && m_prune_target_gb <= m_blockchain_size_gb) { + m_required_space_gb = m_prune_target_gb + m_chain_state_size_gb; storageRequiresMsg = tr("Approximately %1 GB of data will be stored in this directory."); } - ui->lblExplanation3->setVisible(prune_target_gb > 0); + ui->lblExplanation3->setVisible(prune_checked); ui->sizeWarningLabel->setText( tr("%1 will download and store a copy of the Bitcoin block chain.").arg(PACKAGE_NAME) + " " + storageRequiresMsg.arg(m_required_space_gb) + " " + diff --git a/src/qt/intro.h b/src/qt/intro.h index 8375847cc0..732393246e 100644 --- a/src/qt/intro.h +++ b/src/qt/intro.h @@ -72,11 +72,12 @@ private: //! Total required space (in GB) depending on user choice (prune or not prune). int64_t m_required_space_gb{0}; uint64_t m_bytes_available{0}; + const int64_t m_prune_target_gb; void startThread(); void checkPath(const QString &dataDir); QString getPathToCheck(); - void UpdatePruneLabels(int64_t prune_target_gb); + void UpdatePruneLabels(bool prune_checked); void UpdateFreeSpaceLabel(); friend class FreespaceChecker; -- cgit v1.2.3