Skip to content

Commit e6bfd95

Browse files
committed
Merge #881: Move FreespaceChecker class into its own module
3a03f07 qt: Avoid header circular dependency (Anthony Towns) 25884bd qt, refactor: Move `FreespaceChecker` class into its own module (Hennadii Stepanov) Pull request description: For some reason, the MOC compiler in older versions of Qt 6 fails to parse `qt/intro.cpp`, as noted in [this comment](bitcoin/bitcoin#32998 (comment)). This PR proposes a move-only refactoring to simplify the source structure by eliminating the need for the inline `#include <qt/intro.moc>`, thereby effectively working around the issue. Required for bitcoin/bitcoin#32998. ACKs for top commit: ajtowns: ACK 3a03f07 Tree-SHA512: 4a7261f04fff9bd8edd4dc2df619c90e06417e19da672dd688a917cd0b9a324a6db7185a47c48f0385713b5e6c45d2204bef58cbe6c77299386136ed5682bd8d
2 parents 8a94cf8 + 3a03f07 commit e6bfd95

File tree

5 files changed

+117
-90
lines changed

5 files changed

+117
-90
lines changed

src/qt/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ add_library(bitcoinqt STATIC EXCLUDE_FROM_ALL
7575
clientmodel.h
7676
csvmodelwriter.cpp
7777
csvmodelwriter.h
78+
freespacechecker.cpp
79+
freespacechecker.h
7880
guiutil.cpp
7981
guiutil.h
8082
initexecutor.cpp

src/qt/freespacechecker.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright (c) 2011-present The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <qt/freespacechecker.h>
6+
7+
#include <qt/guiutil.h>
8+
#include <util/fs.h>
9+
10+
#include <QDir>
11+
#include <QString>
12+
13+
#include <cstdint>
14+
15+
void FreespaceChecker::check()
16+
{
17+
QString dataDirStr = intro->getPathToCheck();
18+
fs::path dataDir = GUIUtil::QStringToPath(dataDirStr);
19+
uint64_t freeBytesAvailable = 0;
20+
int replyStatus = ST_OK;
21+
QString replyMessage = tr("A new data directory will be created.");
22+
23+
/* Find first parent that exists, so that fs::space does not fail */
24+
fs::path parentDir = dataDir;
25+
fs::path parentDirOld = fs::path();
26+
while(parentDir.has_parent_path() && !fs::exists(parentDir))
27+
{
28+
parentDir = parentDir.parent_path();
29+
30+
/* Check if we make any progress, break if not to prevent an infinite loop here */
31+
if (parentDirOld == parentDir)
32+
break;
33+
34+
parentDirOld = parentDir;
35+
}
36+
37+
try {
38+
freeBytesAvailable = fs::space(parentDir).available;
39+
if(fs::exists(dataDir))
40+
{
41+
if(fs::is_directory(dataDir))
42+
{
43+
QString separator = "<code>" + QDir::toNativeSeparators("/") + tr("name") + "</code>";
44+
replyStatus = ST_OK;
45+
replyMessage = tr("Directory already exists. Add %1 if you intend to create a new directory here.").arg(separator);
46+
} else {
47+
replyStatus = ST_ERROR;
48+
replyMessage = tr("Path already exists, and is not a directory.");
49+
}
50+
}
51+
} catch (const fs::filesystem_error&)
52+
{
53+
/* Parent directory does not exist or is not accessible */
54+
replyStatus = ST_ERROR;
55+
replyMessage = tr("Cannot create data directory here.");
56+
}
57+
Q_EMIT reply(replyStatus, replyMessage, freeBytesAvailable);
58+
}

src/qt/freespacechecker.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright (c) 2011-present The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#ifndef BITCOIN_QT_FREESPACECHECKER_H
6+
#define BITCOIN_QT_FREESPACECHECKER_H
7+
8+
#include <QObject>
9+
#include <QString>
10+
#include <QtGlobal>
11+
12+
/* Check free space asynchronously to prevent hanging the UI thread.
13+
14+
Up to one request to check a path is in flight to this thread; when the check()
15+
function runs, the current path is requested from the associated Intro object.
16+
The reply is sent back through a signal.
17+
18+
This ensures that no queue of checking requests is built up while the user is
19+
still entering the path, and that always the most recently entered path is checked as
20+
soon as the thread becomes available.
21+
*/
22+
class FreespaceChecker : public QObject
23+
{
24+
Q_OBJECT
25+
26+
public:
27+
class PathQuery
28+
{
29+
public:
30+
virtual QString getPathToCheck() = 0;
31+
};
32+
33+
explicit FreespaceChecker(PathQuery* intro) : intro{intro} {}
34+
35+
enum Status {
36+
ST_OK,
37+
ST_ERROR
38+
};
39+
40+
public Q_SLOTS:
41+
void check();
42+
43+
Q_SIGNALS:
44+
void reply(int status, const QString &message, quint64 available);
45+
46+
private:
47+
PathQuery* intro;
48+
};
49+
50+
#endif // BITCOIN_QT_FREESPACECHECKER_H

src/qt/intro.cpp

Lines changed: 2 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2011-2022 The Bitcoin Core developers
1+
// Copyright (c) 2011-present The Bitcoin Core developers
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

@@ -10,6 +10,7 @@
1010
#include <util/chaintype.h>
1111
#include <util/fs.h>
1212

13+
#include <qt/freespacechecker.h>
1314
#include <qt/guiconstants.h>
1415
#include <qt/guiutil.h>
1516
#include <qt/optionsmodel.h>
@@ -25,90 +26,6 @@
2526

2627
#include <cmath>
2728

28-
/* Check free space asynchronously to prevent hanging the UI thread.
29-
30-
Up to one request to check a path is in flight to this thread; when the check()
31-
function runs, the current path is requested from the associated Intro object.
32-
The reply is sent back through a signal.
33-
34-
This ensures that no queue of checking requests is built up while the user is
35-
still entering the path, and that always the most recently entered path is checked as
36-
soon as the thread becomes available.
37-
*/
38-
class FreespaceChecker : public QObject
39-
{
40-
Q_OBJECT
41-
42-
public:
43-
explicit FreespaceChecker(Intro *intro);
44-
45-
enum Status {
46-
ST_OK,
47-
ST_ERROR
48-
};
49-
50-
public Q_SLOTS:
51-
void check();
52-
53-
Q_SIGNALS:
54-
void reply(int status, const QString &message, quint64 available);
55-
56-
private:
57-
Intro *intro;
58-
};
59-
60-
#include <qt/intro.moc>
61-
62-
FreespaceChecker::FreespaceChecker(Intro *_intro)
63-
{
64-
this->intro = _intro;
65-
}
66-
67-
void FreespaceChecker::check()
68-
{
69-
QString dataDirStr = intro->getPathToCheck();
70-
fs::path dataDir = GUIUtil::QStringToPath(dataDirStr);
71-
uint64_t freeBytesAvailable = 0;
72-
int replyStatus = ST_OK;
73-
QString replyMessage = tr("A new data directory will be created.");
74-
75-
/* Find first parent that exists, so that fs::space does not fail */
76-
fs::path parentDir = dataDir;
77-
fs::path parentDirOld = fs::path();
78-
while(parentDir.has_parent_path() && !fs::exists(parentDir))
79-
{
80-
parentDir = parentDir.parent_path();
81-
82-
/* Check if we make any progress, break if not to prevent an infinite loop here */
83-
if (parentDirOld == parentDir)
84-
break;
85-
86-
parentDirOld = parentDir;
87-
}
88-
89-
try {
90-
freeBytesAvailable = fs::space(parentDir).available;
91-
if(fs::exists(dataDir))
92-
{
93-
if(fs::is_directory(dataDir))
94-
{
95-
QString separator = "<code>" + QDir::toNativeSeparators("/") + tr("name") + "</code>";
96-
replyStatus = ST_OK;
97-
replyMessage = tr("Directory already exists. Add %1 if you intend to create a new directory here.").arg(separator);
98-
} else {
99-
replyStatus = ST_ERROR;
100-
replyMessage = tr("Path already exists, and is not a directory.");
101-
}
102-
}
103-
} catch (const fs::filesystem_error&)
104-
{
105-
/* Parent directory does not exist or is not accessible */
106-
replyStatus = ST_ERROR;
107-
replyMessage = tr("Cannot create data directory here.");
108-
}
109-
Q_EMIT reply(replyStatus, replyMessage, freeBytesAvailable);
110-
}
111-
11229
namespace {
11330
//! Return pruning size that will be used if automatic pruning is enabled.
11431
int GetPruneTargetGB()

src/qt/intro.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
// Copyright (c) 2011-2021 The Bitcoin Core developers
1+
// Copyright (c) 2011-present The Bitcoin Core developers
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

55
#ifndef BITCOIN_QT_INTRO_H
66
#define BITCOIN_QT_INTRO_H
77

8+
#include <qt/freespacechecker.h>
9+
810
#include <QDialog>
911
#include <QMutex>
1012
#include <QThread>
1113

1214
static const bool DEFAULT_CHOOSE_DATADIR = false;
1315

14-
class FreespaceChecker;
15-
1616
namespace interfaces {
1717
class Node;
1818
}
@@ -25,7 +25,7 @@ namespace Ui {
2525
Allows the user to choose a data directory,
2626
in which the wallet and block chain will be stored.
2727
*/
28-
class Intro : public QDialog
28+
class Intro : public QDialog, public FreespaceChecker::PathQuery
2929
{
3030
Q_OBJECT
3131

@@ -78,7 +78,7 @@ private Q_SLOTS:
7878

7979
void startThread();
8080
void checkPath(const QString &dataDir);
81-
QString getPathToCheck();
81+
QString getPathToCheck() override;
8282
void UpdatePruneLabels(bool prune_checked);
8383
void UpdateFreeSpaceLabel();
8484

0 commit comments

Comments
 (0)