Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2011-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <bitcoin-build-config.h> // IWYU pragma: keep7#include <chainparams.h>8#include <qt/intro.h>9#include <qt/forms/ui_intro.h>10#include <util/chaintype.h>11#include <util/fs.h>13#include <qt/freespacechecker.h>14#include <qt/guiconstants.h>15#include <qt/guiutil.h>16#include <qt/optionsmodel.h>18#include <common/args.h>19#include <interfaces/node.h>20#include <node/interface_ui.h>21#include <util/fs_helpers.h>22#include <util/translation.h>23#include <validation.h>25#include <QFileDialog>26#include <QSettings>27#include <QMessageBox>29#include <cmath>30#include <cstdlib>32namespace {33//! Return pruning size that will be used if automatic pruning is enabled.34int GetPruneTargetGB()35{36int64_t prune_target_mib = gArgs.GetIntArg("-prune", 0);37// >1 means automatic pruning is enabled by config, 1 means manual pruning, 0 means no pruning.38return prune_target_mib > 1 ? PruneMiBtoGB(prune_target_mib) : DEFAULT_PRUNE_TARGET_GB;39}40} // namespace42Intro::Intro(QWidget *parent, int64_t blockchain_size_gb, int64_t chain_state_size_gb) :43QDialog(parent, GUIUtil::dialog_flags),44ui(new Ui::Intro),45m_blockchain_size_gb(blockchain_size_gb),46m_chain_state_size_gb(chain_state_size_gb),47m_prune_target_gb{GetPruneTargetGB()}48{49ui->setupUi(this);50ui->welcomeLabel->setText(ui->welcomeLabel->text().arg(CLIENT_NAME));51ui->storageLabel->setText(ui->storageLabel->text().arg(CLIENT_NAME));53ui->lblExplanation1->setText(ui->lblExplanation1->text()54.arg(CLIENT_NAME)55.arg(m_blockchain_size_gb)56.arg(2009)57.arg(tr("Bitcoin"))58);59ui->lblExplanation2->setText(ui->lblExplanation2->text().arg(CLIENT_NAME));61const int min_prune_target_GB = std::ceil(MIN_DISK_SPACE_FOR_BLOCK_FILES / 1e9);62ui->pruneGB->setRange(min_prune_target_GB, std::numeric_limits<int>::max());63if (const auto arg{gArgs.GetIntArg("-prune")}) {64m_prune_checkbox_is_default = false;65ui->prune->setChecked(*arg >= 1);66ui->prune->setEnabled(false);67}68ui->pruneGB->setValue(m_prune_target_gb);69ui->pruneGB->setToolTip(ui->prune->toolTip());70ui->lblPruneSuffix->setToolTip(ui->prune->toolTip());71UpdatePruneLabels(ui->prune->isChecked());73connect(ui->prune, &QCheckBox::toggled, [this](bool prune_checked) {74m_prune_checkbox_is_default = false;75UpdatePruneLabels(prune_checked);76UpdateFreeSpaceLabel();77});78connect(ui->pruneGB, qOverload<int>(&QSpinBox::valueChanged), [this](int prune_GB) {79m_prune_target_gb = prune_GB;80UpdatePruneLabels(ui->prune->isChecked());81UpdateFreeSpaceLabel();82});84startThread();85}87Intro::~Intro()88{89delete ui;90/* Ensure thread is finished before it is deleted */91thread->quit();92thread->wait();93}95QString Intro::getDataDirectory()96{97return ui->dataDirectory->text();98}100void Intro::setDataDirectory(const QString &dataDir)101{102ui->dataDirectory->setText(dataDir);103if(dataDir == GUIUtil::getDefaultDataDirectory())104{105ui->dataDirDefault->setChecked(true);106ui->dataDirectory->setEnabled(false);107ui->ellipsisButton->setEnabled(false);108} else {109ui->dataDirCustom->setChecked(true);110ui->dataDirectory->setEnabled(true);111ui->ellipsisButton->setEnabled(true);112}113}115int64_t Intro::getPruneMiB() const116{117switch (ui->prune->checkState()) {118case Qt::Checked:119return PruneGBtoMiB(m_prune_target_gb);120case Qt::Unchecked: default:121return 0;122}123}125bool Intro::showIfNeeded(bool& did_show_intro, int64_t& prune_MiB)126{127did_show_intro = false;129QSettings settings;130/* If data directory provided on command line, no need to look at settings131or show a picking dialog */132if(!gArgs.GetArg("-datadir", "").empty())133return true;134/* 1) Default data directory for operating system */135QString dataDir = GUIUtil::getDefaultDataDirectory();136/* 2) Allow QSettings to override default dir */137dataDir = settings.value("strDataDir", dataDir).toString();139if(!fs::exists(GUIUtil::QStringToPath(dataDir)) || gArgs.GetBoolArg("-choosedatadir", DEFAULT_CHOOSE_DATADIR) || settings.value("fReset", false).toBool() || gArgs.GetBoolArg("-resetguisettings", false))140{141/* Use selectParams here to guarantee Params() can be used by node interface */142try {143SelectParams(gArgs.GetChainType());144} catch (const std::exception& e) {145InitError(Untranslated(e.what()));146QMessageBox::critical(nullptr, CLIENT_NAME, QObject::tr("Error: %1").arg(QString(e.what())));147std::exit(EXIT_FAILURE);148}150/* If current default data directory does not exist, let the user choose one */151Intro intro(nullptr, Params().AssumedBlockchainSize(), Params().AssumedChainStateSize());152intro.setDataDirectory(dataDir);153intro.setWindowIcon(QIcon(":icons/bitcoin"));154did_show_intro = true;156while(true)157{158if(!intro.exec())159{160/* Cancel clicked */161return false;162}163dataDir = intro.getDataDirectory();164try {165if (TryCreateDirectories(GUIUtil::QStringToPath(dataDir))) {166// If a new data directory has been created, make wallets subdirectory too167TryCreateDirectories(GUIUtil::QStringToPath(dataDir) / "wallets");168}169break;170} catch (const fs::filesystem_error&) {171QMessageBox::critical(nullptr, CLIENT_NAME,172tr("Error: Specified data directory \"%1\" cannot be created.").arg(dataDir));173/* fall through, back to choosing screen */174}175}177// Additional preferences:178prune_MiB = intro.getPruneMiB();180settings.setValue("strDataDir", dataDir);181settings.setValue("fReset", false);182}183/* Only override -datadir if different from the default, to make it possible to184* override -datadir in the bitcoin.conf file in the default data directory185* (to be consistent with bitcoind behavior)186*/187if(dataDir != GUIUtil::getDefaultDataDirectory()) {188gArgs.SoftSetArg("-datadir", fs::PathToString(GUIUtil::QStringToPath(dataDir))); // use OS locale for path setting189}190return true;191}193void Intro::setStatus(int status, const QString &message, quint64 bytesAvailable)194{195switch(status)196{197case FreespaceChecker::ST_OK:198ui->errorMessage->setText(message);199ui->errorMessage->setStyleSheet("");200break;201case FreespaceChecker::ST_ERROR:202ui->errorMessage->setText(tr("Error") + ": " + message);203ui->errorMessage->setStyleSheet("QLabel { color: #800000 }");204break;205}206/* Indicate number of bytes available */207if(status == FreespaceChecker::ST_ERROR)208{209ui->freeSpace->setText("");210} else {211m_bytes_available = bytesAvailable;212if (ui->prune->isEnabled() && m_prune_checkbox_is_default) {213ui->prune->setChecked(m_bytes_available < (m_blockchain_size_gb + m_chain_state_size_gb + 10) * GB_BYTES);214}215UpdateFreeSpaceLabel();216}217/* Don't allow confirm in ERROR state */218ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(status != FreespaceChecker::ST_ERROR);219}221void Intro::UpdateFreeSpaceLabel()222{223QString freeString = tr("%n GB of space available", "", m_bytes_available / GB_BYTES);224if (m_bytes_available < m_required_space_gb * GB_BYTES) {225freeString += " " + tr("(of %n GB needed)", "", m_required_space_gb);226ui->freeSpace->setStyleSheet("QLabel { color: #800000 }");227} else if (m_bytes_available / GB_BYTES - m_required_space_gb < 10) {228freeString += " " + tr("(%n GB needed for full chain)", "", m_required_space_gb);229ui->freeSpace->setStyleSheet("QLabel { color: #999900 }");230} else {231ui->freeSpace->setStyleSheet("");232}233ui->freeSpace->setText(freeString + ".");234}236void Intro::on_dataDirectory_textChanged(const QString &dataDirStr)237{238/* Disable OK button until check result comes in */239ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);240checkPath(dataDirStr);241}243void Intro::on_ellipsisButton_clicked()244{245QString dir = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(nullptr, tr("Choose data directory"), ui->dataDirectory->text()));246if(!dir.isEmpty())247ui->dataDirectory->setText(dir);248}250void Intro::on_dataDirDefault_clicked()
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.