Merge #16714: gui: add prune to intro screen with smart default
9924bce317
[gui] intro: enable pruning by default unless disk is big (Sjors Provoost)c8de347a9d
[gui] intro: add prune preference (Sjors Provoost)1bbc49d207
[gui] intro: inform caller if intro was shown (Sjors Provoost)1957103786
[gui] add explicit prune setter (Sjors Provoost)1bccf6a52d
[node] add forceSetArg to interface (Sjors Provoost) Pull request description: This adds a checkbox to the intro screen to enable pruning from the get go. If the user has plenty of space, it's unchecked by default: <img width="671" alt="big" src="https://user-images.githubusercontent.com/10217/63641289-10339000-c6ac-11e9-98d7-caf64dff0da6.png"> If the user has insufficient space it's checked by default: <img width="897" alt="low" src="https://user-images.githubusercontent.com/10217/63641276-d4002f80-c6ab-11e9-9f5b-a53472f814ff.png"> When the user has barely enough space and is likely to need pruning in the near future, this is shown in yellow and we also check the prune box: <img width="662" alt="medium" src="https://user-images.githubusercontent.com/10217/63641294-1c1f5200-c6ac-11e9-8ecb-6b69e42b1ece.png"> The cut-off for this 10 GB above `m_assumed_blockchain_size` (`=240` in `chainparams.cpp`). If the user launches the first time with `-prune=...` then we disable the check box and display the correct size (rounded to GB): <img width="658" alt="Schermafbeelding 2019-08-24 om 20 23 14" src="https://user-images.githubusercontent.com/10217/63641351-09594d00-c6ad-11e9-94fe-fe5ed562e109.png"> The 2 GB default matches the settings default. The user can't change it in the intro screen, but can change it later. I'm tempted to increase that default to 10 GB, and then have the intro screen reduce it if space is really tight. Tips for testing: * move your existing data dir elsewhere * wipe data dir at every restart (behavior is different if it exists) * launch with `bitcoin-qt -resetguisettings -lang=en` (there's some space issues in different languages) * fake your free space by changing `intro.cpp` line 90: `freeBytesAvailable = 5000000000; // 5 GB` * try both testnet and mainnet, because settings are seperate. In particular note how step 7 in `GuiMain` switches where `QTSettings settings` points to; this had me thoroughly confused on testnet, because I was setting them too early. ACKs for top commit: jonasschnelli: Tested ACK9924bce317
ryanofsky: utACK9924bce317
. The changes are very logical, and implement the feature in a clean that way that doesn't add a lot of complication and shouldn't interfere with future improvements. I looked at Luke's branch too, and I think there's also a lot of great stuff there that seems fully compatible with this change. Tree-SHA512: 9523961451c53aebd347716976bc3a4a398f989dc21e9bbbd357060bd11a8f46c435f068bd421bb31ccb08e55445ef67bc347d8d19a4fb8fde9d6d3f9a3bcbb0
This commit is contained in:
commit
884f7cc81b
9 changed files with 68 additions and 9 deletions
|
@ -62,6 +62,7 @@ public:
|
||||||
return gArgs.ParseParameters(argc, argv, error);
|
return gArgs.ParseParameters(argc, argv, error);
|
||||||
}
|
}
|
||||||
bool readConfigFiles(std::string& error) override { return gArgs.ReadConfigFiles(error, true); }
|
bool readConfigFiles(std::string& error) override { return gArgs.ReadConfigFiles(error, true); }
|
||||||
|
void forceSetArg(const std::string& arg, const std::string& value) override { gArgs.ForceSetArg(arg, value); }
|
||||||
bool softSetArg(const std::string& arg, const std::string& value) override { return gArgs.SoftSetArg(arg, value); }
|
bool softSetArg(const std::string& arg, const std::string& value) override { return gArgs.SoftSetArg(arg, value); }
|
||||||
bool softSetBoolArg(const std::string& arg, bool value) override { return gArgs.SoftSetBoolArg(arg, value); }
|
bool softSetBoolArg(const std::string& arg, bool value) override { return gArgs.SoftSetBoolArg(arg, value); }
|
||||||
void selectParams(const std::string& network) override { SelectParams(network); }
|
void selectParams(const std::string& network) override { SelectParams(network); }
|
||||||
|
|
|
@ -46,6 +46,9 @@ public:
|
||||||
//! Set command line arguments.
|
//! Set command line arguments.
|
||||||
virtual bool parseParameters(int argc, const char* const argv[], std::string& error) = 0;
|
virtual bool parseParameters(int argc, const char* const argv[], std::string& error) = 0;
|
||||||
|
|
||||||
|
//! Set a command line argument
|
||||||
|
virtual void forceSetArg(const std::string& arg, const std::string& value) = 0;
|
||||||
|
|
||||||
//! Set a command line argument if it doesn't already have a value
|
//! Set a command line argument if it doesn't already have a value
|
||||||
virtual bool softSetArg(const std::string& arg, const std::string& value) = 0;
|
virtual bool softSetArg(const std::string& arg, const std::string& value) = 0;
|
||||||
|
|
||||||
|
|
|
@ -282,6 +282,10 @@ void BitcoinApplication::parameterSetup()
|
||||||
m_node.initParameterInteraction();
|
m_node.initParameterInteraction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BitcoinApplication::SetPrune(bool prune, bool force) {
|
||||||
|
optionsModel->SetPrune(prune, force);
|
||||||
|
}
|
||||||
|
|
||||||
void BitcoinApplication::requestInitialize()
|
void BitcoinApplication::requestInitialize()
|
||||||
{
|
{
|
||||||
qDebug() << __func__ << ": Requesting initialize";
|
qDebug() << __func__ << ": Requesting initialize";
|
||||||
|
@ -487,8 +491,10 @@ int GuiMain(int argc, char* argv[])
|
||||||
|
|
||||||
/// 5. Now that settings and translations are available, ask user for data directory
|
/// 5. Now that settings and translations are available, ask user for data directory
|
||||||
// User language is set up: pick a data directory
|
// User language is set up: pick a data directory
|
||||||
if (!Intro::pickDataDirectory(*node))
|
bool did_show_intro = false;
|
||||||
return EXIT_SUCCESS;
|
bool prune = false; // Intro dialog prune check box
|
||||||
|
// Gracefully exit if the user cancels
|
||||||
|
if (!Intro::showIfNeeded(*node, did_show_intro, prune)) return EXIT_SUCCESS;
|
||||||
|
|
||||||
/// 6. Determine availability of data directory and parse bitcoin.conf
|
/// 6. Determine availability of data directory and parse bitcoin.conf
|
||||||
/// - Do not call GetDataDir(true) before this step finishes
|
/// - Do not call GetDataDir(true) before this step finishes
|
||||||
|
@ -562,6 +568,11 @@ int GuiMain(int argc, char* argv[])
|
||||||
// Load GUI settings from QSettings
|
// Load GUI settings from QSettings
|
||||||
app.createOptionsModel(gArgs.GetBoolArg("-resetguisettings", false));
|
app.createOptionsModel(gArgs.GetBoolArg("-resetguisettings", false));
|
||||||
|
|
||||||
|
if (did_show_intro) {
|
||||||
|
// Store intro dialog settings other than datadir (network specific)
|
||||||
|
app.SetPrune(prune, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (gArgs.GetBoolArg("-splash", DEFAULT_SPLASHSCREEN) && !gArgs.GetBoolArg("-min", false))
|
if (gArgs.GetBoolArg("-splash", DEFAULT_SPLASHSCREEN) && !gArgs.GetBoolArg("-min", false))
|
||||||
app.createSplashScreen(networkStyle.data());
|
app.createSplashScreen(networkStyle.data());
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,8 @@ public:
|
||||||
void parameterSetup();
|
void parameterSetup();
|
||||||
/// Create options model
|
/// Create options model
|
||||||
void createOptionsModel(bool resetSettings);
|
void createOptionsModel(bool resetSettings);
|
||||||
|
/// Update prune value
|
||||||
|
void SetPrune(bool prune, bool force = false);
|
||||||
/// Create main window
|
/// Create main window
|
||||||
void createWindow(const NetworkStyle *networkStyle);
|
void createWindow(const NetworkStyle *networkStyle);
|
||||||
/// Create splash screen
|
/// Create splash screen
|
||||||
|
|
|
@ -210,6 +210,16 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="prune">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Reverting this setting requires re-downloading the entire blockchain. It is faster to download the full chain first and prune it later. Disables some advanced features.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="lblExplanation2">
|
<widget class="QLabel" name="lblExplanation2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
|
|
@ -131,6 +131,11 @@ Intro::Intro(QWidget *parent, uint64_t blockchain_size, uint64_t chain_state_siz
|
||||||
ui->lblExplanation2->setText(ui->lblExplanation2->text().arg(PACKAGE_NAME));
|
ui->lblExplanation2->setText(ui->lblExplanation2->text().arg(PACKAGE_NAME));
|
||||||
|
|
||||||
uint64_t pruneTarget = std::max<int64_t>(0, gArgs.GetArg("-prune", 0));
|
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
|
||||||
|
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 : 2));
|
||||||
requiredSpace = m_blockchain_size;
|
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.");
|
QString storageRequiresMsg = tr("At least %1 GB of data will be stored in this directory, and it will grow over time.");
|
||||||
if (pruneTarget) {
|
if (pruneTarget) {
|
||||||
|
@ -180,8 +185,10 @@ void Intro::setDataDirectory(const QString &dataDir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Intro::pickDataDirectory(interfaces::Node& node)
|
bool Intro::showIfNeeded(interfaces::Node& node, bool& did_show_intro, bool& prune)
|
||||||
{
|
{
|
||||||
|
did_show_intro = false;
|
||||||
|
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
/* If data directory provided on command line, no need to look at settings
|
/* If data directory provided on command line, no need to look at settings
|
||||||
or show a picking dialog */
|
or show a picking dialog */
|
||||||
|
@ -205,6 +212,7 @@ bool Intro::pickDataDirectory(interfaces::Node& node)
|
||||||
Intro intro(0, node.getAssumedBlockchainSize(), node.getAssumedChainStateSize());
|
Intro intro(0, node.getAssumedBlockchainSize(), node.getAssumedChainStateSize());
|
||||||
intro.setDataDirectory(dataDir);
|
intro.setDataDirectory(dataDir);
|
||||||
intro.setWindowIcon(QIcon(":icons/bitcoin"));
|
intro.setWindowIcon(QIcon(":icons/bitcoin"));
|
||||||
|
did_show_intro = true;
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
|
@ -227,6 +235,9 @@ bool Intro::pickDataDirectory(interfaces::Node& node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Additional preferences:
|
||||||
|
prune = intro.ui->prune->isChecked();
|
||||||
|
|
||||||
settings.setValue("strDataDir", dataDir);
|
settings.setValue("strDataDir", dataDir);
|
||||||
settings.setValue("fReset", false);
|
settings.setValue("fReset", false);
|
||||||
}
|
}
|
||||||
|
@ -263,6 +274,11 @@ void Intro::setStatus(int status, const QString &message, quint64 bytesAvailable
|
||||||
{
|
{
|
||||||
freeString += " " + tr("(of %n GB needed)", "", requiredSpace);
|
freeString += " " + tr("(of %n GB needed)", "", requiredSpace);
|
||||||
ui->freeSpace->setStyleSheet("QLabel { color: #800000 }");
|
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 {
|
} else {
|
||||||
ui->freeSpace->setStyleSheet("");
|
ui->freeSpace->setStyleSheet("");
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine data directory. Let the user choose if the current one doesn't exist.
|
* Determine data directory. Let the user choose if the current one doesn't exist.
|
||||||
|
* Let the user configure additional preferences such as pruning.
|
||||||
*
|
*
|
||||||
* @returns true if a data directory was selected, false if the user cancelled the selection
|
* @returns true if a data directory was selected, false if the user cancelled the selection
|
||||||
* dialog.
|
* dialog.
|
||||||
|
@ -46,7 +47,7 @@ public:
|
||||||
* @note do NOT call global GetDataDir() before calling this function, this
|
* @note do NOT call global GetDataDir() before calling this function, this
|
||||||
* will cause the wrong path to be cached.
|
* will cause the wrong path to be cached.
|
||||||
*/
|
*/
|
||||||
static bool pickDataDirectory(interfaces::Node& node);
|
static bool showIfNeeded(interfaces::Node& node, bool& did_show_intro, bool& prune);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void requestCheck();
|
void requestCheck();
|
||||||
|
|
|
@ -92,11 +92,7 @@ void OptionsModel::Init(bool resetSettings)
|
||||||
settings.setValue("bPrune", false);
|
settings.setValue("bPrune", false);
|
||||||
if (!settings.contains("nPruneSize"))
|
if (!settings.contains("nPruneSize"))
|
||||||
settings.setValue("nPruneSize", 2);
|
settings.setValue("nPruneSize", 2);
|
||||||
// Convert prune size from GB to MiB:
|
SetPrune(settings.value("bPrune").toBool());
|
||||||
const uint64_t nPruneSizeMiB = (settings.value("nPruneSize").toInt() * GB_BYTES) >> 20;
|
|
||||||
if (!m_node.softSetArg("-prune", settings.value("bPrune").toBool() ? std::to_string(nPruneSizeMiB) : "0")) {
|
|
||||||
addOverriddenOption("-prune");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!settings.contains("nDatabaseCache"))
|
if (!settings.contains("nDatabaseCache"))
|
||||||
settings.setValue("nDatabaseCache", (qint64)nDefaultDbCache);
|
settings.setValue("nDatabaseCache", (qint64)nDefaultDbCache);
|
||||||
|
@ -240,6 +236,22 @@ static const QString GetDefaultProxyAddress()
|
||||||
return QString("%1:%2").arg(DEFAULT_GUI_PROXY_HOST).arg(DEFAULT_GUI_PROXY_PORT);
|
return QString("%1:%2").arg(DEFAULT_GUI_PROXY_HOST).arg(DEFAULT_GUI_PROXY_PORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OptionsModel::SetPrune(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";
|
||||||
|
if (force) {
|
||||||
|
m_node.forceSetArg("-prune", prune_val);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!m_node.softSetArg("-prune", prune_val)) {
|
||||||
|
addOverriddenOption("-prune");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// read QSettings values and return them
|
// read QSettings values and return them
|
||||||
QVariant OptionsModel::data(const QModelIndex & index, int role) const
|
QVariant OptionsModel::data(const QModelIndex & index, int role) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -77,6 +77,9 @@ public:
|
||||||
bool getCoinControlFeatures() const { return fCoinControlFeatures; }
|
bool getCoinControlFeatures() const { return fCoinControlFeatures; }
|
||||||
const QString& getOverriddenByCommandLine() { return strOverriddenByCommandLine; }
|
const QString& getOverriddenByCommandLine() { return strOverriddenByCommandLine; }
|
||||||
|
|
||||||
|
/* Explicit setters */
|
||||||
|
void SetPrune(bool prune, bool force = false);
|
||||||
|
|
||||||
/* Restart flag helper */
|
/* Restart flag helper */
|
||||||
void setRestartRequired(bool fRequired);
|
void setRestartRequired(bool fRequired);
|
||||||
bool isRestartRequired() const;
|
bool isRestartRequired() const;
|
||||||
|
|
Loading…
Reference in a new issue