Merge #17453: gui: Fix intro dialog labels when the prune button is toggled

4f7127d1e3 gui: Make Intro consistent with prune checkbox (Hennadii Stepanov)
4824a7d36c gui: Add Intro::UpdateFreeSpaceLabel() (Hennadii Stepanov)
daa3f3fa90 refactor: Add Intro::UpdatePruneLabels() (Hennadii Stepanov)
e4caa82a03 refactor: Replace static variable with data member (Hennadii Stepanov)
2bede28cd9 util: Add PruneGBtoMiB() function (Hennadii Stepanov)
e35e4b2ba0 util: Add PruneMiBtoGB() function (Hennadii Stepanov)

Pull request description:

  On master (a6f6333ba2) and on 0.19.0.1 the intro dialog with prune enabled (checkbox "Discard blocks..." is checked) provides a user with wrong info about the required disk space:

  ![DeepinScreenshot_bitcoin-qt_20191208112228](https://user-images.githubusercontent.com/32963518/70387510-8daab400-19ae-11ea-9338-29add9c31118.png)

  Also the paragraph "If you have chosen to limit..." is missed.

  ---

  With this PR 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):
  ![Screenshot from 2019-12-08 11-34-53](https://user-images.githubusercontent.com/32963518/70387542-eed28780-19ae-11ea-9565-49d8a64b2f33.png)

  ---

  This PR is an alternative to #17035.

  **ryanofsky**'s [suggestion](https://github.com/bitcoin/bitcoin/pull/17035#discussion_r337594268) also has been implemented.

ACKs for top commit:
  emilengler:
    ACK 4f7127d1e3
  Sjors:
    tACK 4f7127d1e3
  ryanofsky:
    Code review ACK 4f7127d1e3. It seems like there are a few visible changes here:
  jonasschnelli:
    utACK 4f7127d1e3

Tree-SHA512: fa0bbdcfafde97d7906cda066cbd4608b936a71cae1b4cda3ee3aa2eed3a9795f279f14c6b1b4997278e094db891c7d3bb695368ba0882347aa42165a86e5172
This commit is contained in:
Jonas Schnelli 2020-01-27 18:15:32 +01:00
commit b89f2d0599
No known key found for this signature in database
GPG key ID: 1EB776BB03C7922D
4 changed files with 82 additions and 48 deletions

View file

@ -12,6 +12,7 @@
#include <qt/guiconstants.h>
#include <qt/guiutil.h>
#include <qt/optionsmodel.h>
#include <interfaces/node.h>
#include <util/system.h>
@ -22,9 +23,6 @@
#include <cmath>
/* Total required space (in GB) depending on user choice (prune, not prune) */
static uint64_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()
@ -109,14 +107,24 @@ 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, 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),
m_prune_target_gb{GetPruneTargetGB()}
{
ui->setupUi(this);
ui->welcomeLabel->setText(ui->welcomeLabel->text().arg(PACKAGE_NAME));
@ -124,37 +132,24 @@ 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"))
);
ui->lblExplanation2->setText(ui->lblExplanation2->text().arg(PACKAGE_NAME));
uint64_t pruneTarget = std::max<int64_t>(0, gArgs.GetArg("-prune", 0));
if (pruneTarget > 1) { // -prune=1 means enabled, above that it's a size in MB
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);
}
ui->prune->setText(tr("Discard blocks after verification, except most recent %1 GB (prune)").arg(pruneTarget ? pruneTarget / 1000 : 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;
storageRequiresMsg = tr("Approximately %1 GB of data will be stored in this directory.");
}
ui->lblExplanation3->setVisible(true);
} else {
ui->lblExplanation3->setVisible(false);
}
requiredSpace += m_chain_state_size;
ui->sizeWarningLabel->setText(
tr("%1 will download and store a copy of the Bitcoin block chain.").arg(PACKAGE_NAME) + " " +
storageRequiresMsg.arg(requiredSpace) + " " +
tr("The wallet will also be stored in this directory.")
);
this->adjustSize();
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();
}
@ -270,25 +265,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 < requiredSpace * GB_BYTES)
{
freeString += " " + tr("(of %n GB needed)", "", requiredSpace);
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);
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 */
@ -349,3 +350,20 @@ QString Intro::getPathToCheck()
mutex.unlock();
return retval;
}
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 (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_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) + " " +
tr("The wallet will also be stored in this directory.")
);
this->adjustSize();
}

View file

@ -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,12 +67,18 @@ 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};
uint64_t m_bytes_available{0};
const int64_t m_prune_target_gb;
void startThread();
void checkPath(const QString &dataDir);
QString getPathToCheck();
void UpdatePruneLabels(bool prune_checked);
void UpdateFreeSpaceLabel();
friend class FreespaceChecker;
};

View file

@ -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;

View file

@ -6,6 +6,7 @@
#define BITCOIN_QT_OPTIONSMODEL_H
#include <amount.h>
#include <qt/guiconstants.h>
#include <QAbstractListModel>
@ -16,6 +17,16 @@ 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; }
/**
* 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.