aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/utils/fileutils.h
blob: b20f7568dbee39729d4ddcffe0bf88b8ffd8c666 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0

#pragma once

#include "utils_global.h"

#include "filepath.h"

#include <QCoreApplication>
#include <QDir>

#ifdef QT_WIDGETS_LIB
#include <QFileDialog>
#endif

#include <functional>
#include <memory>

QT_BEGIN_NAMESPACE
class QDataStream;
class QTextStream;
class QWidget;
class QXmlStreamWriter;

// for withNtfsPermissions
#ifdef Q_OS_WIN
extern Q_CORE_EXPORT int qt_ntfs_permission_lookup;
#endif
QT_END_NAMESPACE

namespace Utils {

class CommandLine;

struct QTCREATOR_UTILS_EXPORT RunResult
{
    int exitCode = -1;
    QByteArray stdOut;
    QByteArray stdErr;
};

class QTCREATOR_UTILS_EXPORT FileUtils
{
public:
#ifdef QT_GUI_LIB
    class QTCREATOR_UTILS_EXPORT CopyAskingForOverwrite
    {
    public:
        CopyAskingForOverwrite(QWidget *dialogParent,
                               const std::function<void(FilePath)> &postOperation = {});
        bool operator()(const FilePath &src, const FilePath &dest, QString *error);
        FilePaths files() const;

    private:
        QWidget *m_parent;
        FilePaths m_files;
        std::function<void(FilePath)> m_postOperation;
        bool m_overwriteAll = false;
        bool m_skipAll = false;
    };
#endif // QT_GUI_LIB

    static bool copyRecursively(
        const FilePath &srcFilePath,
        const FilePath &tgtFilePath,
        QString *error,
        std::function<bool(const FilePath &, const FilePath &, QString *)> helper);

    static bool copyIfDifferent(const FilePath &srcFilePath,
                                const FilePath &tgtFilePath);
    static QString fileSystemFriendlyName(const QString &name);
    static int indexOfQmakeUnfriendly(const QString &name, int startpos = 0);
    static QString qmakeFriendlyName(const QString &name);
    static bool makeWritable(const FilePath &path);
    static QString normalizedPathName(const QString &name);

    static FilePath commonPath(const FilePath &oldCommonPath, const FilePath &fileName);
    static FilePath commonPath(const FilePaths &paths);
    static FilePath homePath();

    static FilePaths toFilePathList(const QStringList &paths);

    static qint64 bytesAvailableFromDFOutput(const QByteArray &dfOutput);

    static FilePathInfo filePathInfoFromTriple(const QString &infos, int modeBase);

    //! Returns known paths like /opt/homebrew on macOS that might not be in PATH
    static FilePaths usefulExtraSearchPaths();

#ifdef QT_WIDGETS_LIB
    static void setDialogParentGetter(const std::function<QWidget *()> &getter);

    static bool hasNativeFileDialog();

    static FilePath getOpenFilePath(QWidget *parent,
                                    const QString &caption,
                                    const FilePath &dir = {},
                                    const QString &filter = {},
                                    QString *selectedFilter = nullptr,
                                    QFileDialog::Options options = {},
                                    bool fromDeviceIfShiftIsPressed = false,
                                    bool forceNonNativeDialog = false);

    static FilePath getSaveFilePath(QWidget *parent,
                                    const QString &caption,
                                    const FilePath &dir = {},
                                    const QString &filter = {},
                                    QString *selectedFilter = nullptr,
                                    QFileDialog::Options options = {},
                                    bool forceNonNativeDialog = false);

    static FilePath getExistingDirectory(QWidget *parent,
                                         const QString &caption,
                                         const FilePath &dir = {},
                                         QFileDialog::Options options = QFileDialog::ShowDirsOnly,
                                         bool fromDeviceIfShiftIsPressed = false,
                                         bool forceNonNativeDialog = false);

    static FilePaths getOpenFilePaths(QWidget *parent,
                                      const QString &caption,
                                      const FilePath &dir = {},
                                      const QString &filter = {},
                                      QString *selectedFilter = nullptr,
                                      QFileDialog::Options options = {});
#endif
};

// for actually finding out if e.g. directories are writable on Windows
#ifdef Q_OS_WIN

template <typename T>
T withNtfsPermissions(const std::function<T()> &task)
{
    qt_ntfs_permission_lookup++;
    T result = task();
    qt_ntfs_permission_lookup--;
    return result;
}

template <>
QTCREATOR_UTILS_EXPORT void withNtfsPermissions(const std::function<void()> &task);

#else // Q_OS_WIN

template <typename T>
T withNtfsPermissions(const std::function<T()> &task)
{
    return task();
}

#endif // Q_OS_WIN

class QTCREATOR_UTILS_EXPORT FileReader
{
public:
    static QByteArray fetchQrc(const QString &fileName); // Only for internal resources
    bool fetch(const FilePath &filePath, QIODevice::OpenMode mode = QIODevice::NotOpen); // QIODevice::ReadOnly is implicit
    bool fetch(const FilePath &filePath, QIODevice::OpenMode mode, QString *errorString);
    bool fetch(const FilePath &filePath, QString *errorString)
        { return fetch(filePath, QIODevice::NotOpen, errorString); }
#ifdef QT_GUI_LIB
    bool fetch(const FilePath &filePath, QIODevice::OpenMode mode, QWidget *parent);
    bool fetch(const FilePath &filePath, QWidget *parent)
        { return fetch(filePath, QIODevice::NotOpen, parent); }
#endif // QT_GUI_LIB
    const QByteArray &data() const { return m_data; }
    const QString &errorString() const { return m_errorString; }
private:
    QByteArray m_data;
    QString m_errorString;
};

class QTCREATOR_UTILS_EXPORT FileSaverBase
{
public:
    FileSaverBase();
    virtual ~FileSaverBase();

    FilePath filePath() const { return m_filePath; }
    bool hasError() const { return m_hasError; }
    QString errorString() const { return m_errorString; }
    virtual bool finalize();
    bool finalize(QString *errStr);
#ifdef QT_GUI_LIB
    bool finalize(QWidget *parent);
#endif

    bool write(const char *data, int len);
    bool write(const QByteArray &bytes);
    bool setResult(QTextStream *stream);
    bool setResult(QDataStream *stream);
    bool setResult(QXmlStreamWriter *stream);
    bool setResult(bool ok);

    QFile *file() { return m_file.get(); }

protected:
    std::unique_ptr<QFile> m_file;
    FilePath m_filePath;
    QString m_errorString;
    bool m_hasError = false;

private:
    Q_DISABLE_COPY(FileSaverBase)
};

class QTCREATOR_UTILS_EXPORT FileSaver : public FileSaverBase
{
public:
    // QIODevice::WriteOnly is implicit
    explicit FileSaver(const FilePath &filePath, QIODevice::OpenMode mode = QIODevice::NotOpen);

    bool finalize() override;
    using FileSaverBase::finalize;

private:
    bool m_isSafe = false;
};

class QTCREATOR_UTILS_EXPORT TempFileSaver : public FileSaverBase
{
public:
    explicit TempFileSaver(const QString &templ = QString());
    explicit TempFileSaver(const FilePath &templ);
    ~TempFileSaver() override;

    void setAutoRemove(bool on) { m_autoRemove = on; }

protected:
    void initFromString(const QString &templ);

private:
    bool m_autoRemove = true;
};

QTCREATOR_UTILS_EXPORT QTextStream &operator<<(QTextStream &s, const FilePath &fn);

bool isRelativePathHelper(const QString &path, OsType osType);

} // namespace Utils