From 25884bd89684262b94e09c9904c1560d5ba87d86 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 17 Jul 2025 14:40:26 +0100 Subject: [PATCH] qt, refactor: Move `FreespaceChecker` class into its own module --- src/qt/CMakeLists.txt | 2 + src/qt/freespacechecker.cpp | 64 ++++++++++++++++++ src/qt/freespacechecker.h | 46 +++++++++++++ src/qt/intro.cpp | 87 +------------------------ src/qt/intro.h | 2 +- test/lint/lint-circular-dependencies.py | 1 + 6 files changed, 116 insertions(+), 86 deletions(-) create mode 100644 src/qt/freespacechecker.cpp create mode 100644 src/qt/freespacechecker.h diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index c4f13e29d4d..87a5a2bef3b 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -75,6 +75,8 @@ add_library(bitcoinqt STATIC EXCLUDE_FROM_ALL clientmodel.h csvmodelwriter.cpp csvmodelwriter.h + freespacechecker.cpp + freespacechecker.h guiutil.cpp guiutil.h initexecutor.cpp diff --git a/src/qt/freespacechecker.cpp b/src/qt/freespacechecker.cpp new file mode 100644 index 00000000000..e0f6fff3183 --- /dev/null +++ b/src/qt/freespacechecker.cpp @@ -0,0 +1,64 @@ +// Copyright (c) 2011-present The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include + +#include +#include + +#include + +FreespaceChecker::FreespaceChecker(Intro *_intro) +{ + this->intro = _intro; +} + +void FreespaceChecker::check() +{ + QString dataDirStr = intro->getPathToCheck(); + fs::path dataDir = GUIUtil::QStringToPath(dataDirStr); + uint64_t freeBytesAvailable = 0; + int replyStatus = ST_OK; + QString replyMessage = tr("A new data directory will be created."); + + /* Find first parent that exists, so that fs::space does not fail */ + fs::path parentDir = dataDir; + fs::path parentDirOld = fs::path(); + while(parentDir.has_parent_path() && !fs::exists(parentDir)) + { + parentDir = parentDir.parent_path(); + + /* Check if we make any progress, break if not to prevent an infinite loop here */ + if (parentDirOld == parentDir) + break; + + parentDirOld = parentDir; + } + + try { + freeBytesAvailable = fs::space(parentDir).available; + if(fs::exists(dataDir)) + { + if(fs::is_directory(dataDir)) + { + QString separator = "" + QDir::toNativeSeparators("/") + tr("name") + ""; + replyStatus = ST_OK; + replyMessage = tr("Directory already exists. Add %1 if you intend to create a new directory here.").arg(separator); + } else { + replyStatus = ST_ERROR; + replyMessage = tr("Path already exists, and is not a directory."); + } + } + } catch (const fs::filesystem_error&) + { + /* Parent directory does not exist or is not accessible */ + replyStatus = ST_ERROR; + replyMessage = tr("Cannot create data directory here."); + } + Q_EMIT reply(replyStatus, replyMessage, freeBytesAvailable); +} diff --git a/src/qt/freespacechecker.h b/src/qt/freespacechecker.h new file mode 100644 index 00000000000..ebd36bde974 --- /dev/null +++ b/src/qt/freespacechecker.h @@ -0,0 +1,46 @@ +// Copyright (c) 2011-present The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_QT_FREESPACECHECKER_H +#define BITCOIN_QT_FREESPACECHECKER_H + +#include +#include +#include + +class Intro; + +/* 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() + function runs, the current path is requested from the associated Intro object. + The reply is sent back through a signal. + + This ensures that no queue of checking requests is built up while the user is + still entering the path, and that always the most recently entered path is checked as + soon as the thread becomes available. +*/ +class FreespaceChecker : public QObject +{ + Q_OBJECT + +public: + explicit FreespaceChecker(Intro *intro); + + enum Status { + ST_OK, + ST_ERROR + }; + +public Q_SLOTS: + void check(); + +Q_SIGNALS: + void reply(int status, const QString &message, quint64 available); + +private: + Intro *intro; +}; + +#endif // BITCOIN_QT_FREESPACECHECKER_H diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 81814238554..91078b7cc1b 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2022 The Bitcoin Core developers +// Copyright (c) 2011-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -25,90 +26,6 @@ #include -/* 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() - function runs, the current path is requested from the associated Intro object. - The reply is sent back through a signal. - - This ensures that no queue of checking requests is built up while the user is - still entering the path, and that always the most recently entered path is checked as - soon as the thread becomes available. -*/ -class FreespaceChecker : public QObject -{ - Q_OBJECT - -public: - explicit FreespaceChecker(Intro *intro); - - enum Status { - ST_OK, - ST_ERROR - }; - -public Q_SLOTS: - void check(); - -Q_SIGNALS: - void reply(int status, const QString &message, quint64 available); - -private: - Intro *intro; -}; - -#include - -FreespaceChecker::FreespaceChecker(Intro *_intro) -{ - this->intro = _intro; -} - -void FreespaceChecker::check() -{ - QString dataDirStr = intro->getPathToCheck(); - fs::path dataDir = GUIUtil::QStringToPath(dataDirStr); - uint64_t freeBytesAvailable = 0; - int replyStatus = ST_OK; - QString replyMessage = tr("A new data directory will be created."); - - /* Find first parent that exists, so that fs::space does not fail */ - fs::path parentDir = dataDir; - fs::path parentDirOld = fs::path(); - while(parentDir.has_parent_path() && !fs::exists(parentDir)) - { - parentDir = parentDir.parent_path(); - - /* Check if we make any progress, break if not to prevent an infinite loop here */ - if (parentDirOld == parentDir) - break; - - parentDirOld = parentDir; - } - - try { - freeBytesAvailable = fs::space(parentDir).available; - if(fs::exists(dataDir)) - { - if(fs::is_directory(dataDir)) - { - QString separator = "" + QDir::toNativeSeparators("/") + tr("name") + ""; - replyStatus = ST_OK; - replyMessage = tr("Directory already exists. Add %1 if you intend to create a new directory here.").arg(separator); - } else { - replyStatus = ST_ERROR; - replyMessage = tr("Path already exists, and is not a directory."); - } - } - } catch (const fs::filesystem_error&) - { - /* Parent directory does not exist or is not accessible */ - replyStatus = ST_ERROR; - replyMessage = tr("Cannot create data directory here."); - } - Q_EMIT reply(replyStatus, replyMessage, freeBytesAvailable); -} - namespace { //! Return pruning size that will be used if automatic pruning is enabled. int GetPruneTargetGB() diff --git a/src/qt/intro.h b/src/qt/intro.h index 7b34c73b025..1fac5c39531 100644 --- a/src/qt/intro.h +++ b/src/qt/intro.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2021 The Bitcoin Core developers +// Copyright (c) 2011-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/test/lint/lint-circular-dependencies.py b/test/lint/lint-circular-dependencies.py index 9554e560650..2ec79724d10 100755 --- a/test/lint/lint-circular-dependencies.py +++ b/test/lint/lint-circular-dependencies.py @@ -16,6 +16,7 @@ EXPECTED_CIRCULAR_DEPENDENCIES = ( "node/blockstorage -> validation -> node/blockstorage", "node/utxo_snapshot -> validation -> node/utxo_snapshot", "qt/addresstablemodel -> qt/walletmodel -> qt/addresstablemodel", + "qt/freespacechecker -> qt/intro -> qt/freespacechecker", "qt/recentrequeststablemodel -> qt/walletmodel -> qt/recentrequeststablemodel", "qt/sendcoinsdialog -> qt/walletmodel -> qt/sendcoinsdialog", "qt/transactiontablemodel -> qt/walletmodel -> qt/transactiontablemodel",