Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmldomfilewriter.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <QtCore/qrandom.h>
7#include <QtCore/qscopeguard.h>
8#include <QtCore/qtextstream.h>
9
11namespace QQmlJS {
12namespace Dom {
13
14FileWriter::Status FileWriter::write(const QString &tFile, function_ref<bool(QTextStream &)> write)
15{
16 if (shouldRemoveTempFile)
17 tempFile.remove();
18 tempFile.close();
20 Q_ASSERT(status != Status::ShouldWrite);
21 status = Status::ShouldWrite;
22 targetFile = tFile;
23 warnings.clear();
24
25 int i = 0;
26 const int maxAttempts = 20;
27 for (; i < maxAttempts; ++i) {
28 tempFile.setFileName(targetFile
29 + QString::number(QRandomGenerator::global()->generate(), 16).mid(0, 8)
30 + QStringLiteral(u".tmp"));
31 if (tempFile.open(QIODevice::ReadWrite | QIODevice::NewOnly))
32 break;
33 }
34 if (i == maxAttempts) {
35 warnings.append(tr("Could not create temp file for %1").arg(targetFile));
36 status = FileWriter::Status::SkippedDueToFailure;
37 return status;
38 }
40 bool success = false;
41 QTextStream inF(&tempFile);
42 QT_TRY
43 {
44 auto cleanup = qScopeGuard([this, &inF, &success] {
45 inF.flush();
46 tempFile.flush();
47 tempFile.close();
48 if (success) {
49 if (QFile::exists(targetFile)) {
50 // compareFiles
51 if (tempFile.open(QIODevice::ReadOnly)) {
52 auto closeTmpF = qScopeGuard([this] { tempFile.close(); });
53 QFile oldF(targetFile);
54 if (oldF.open(QIODevice::ReadOnly)) {
55 bool same = true;
56 while (!tempFile.atEnd() && !oldF.atEnd()) {
57 QByteArray l1 = tempFile.readLine();
58 QByteArray l2 = oldF.readLine();
59 if (l1 != l2)
60 same = false;
61 }
62 if (tempFile.atEnd() && oldF.atEnd() && same) {
63 tempFile.remove();
64 shouldRemoveTempFile = false;
65 status = Status::SkippedEqual;
66 return;
67 }
68 }
69 }
70 }
71 // move to target
72 if (QFile::exists(targetFile))
73 QFile::remove(targetFile);
74 if (tempFile.rename(targetFile)) {
75 status = Status::DidWrite;
76 shouldRemoveTempFile = false;
77 } else {
78 warnings.append(tr("Rename of file %1 to %2 failed")
79 .arg(tempFile.fileName(), targetFile));
80 status = Status::SkippedDueToFailure;
81 }
82 } else {
83 warnings.append(tr("Error while writing"));
84 }
85 });
86 success = write(inF);
87 }
88 QT_CATCH(...)
89 {
90 warnings.append(tr("Exception trying to write file %1").arg(targetFile));
91 status = FileWriter::Status::SkippedDueToFailure;
92 }
93 if (status == Status::ShouldWrite)
94 status = Status::SkippedDueToFailure;
95 return status;
96}
97
98} // namespace Dom
99} // namespace QQmlJS
100QT_END_NAMESPACE
101
102#include "moc_qqmldomfilewriter_p.cpp"
Status write(const QString &targetFile, function_ref< bool(QTextStream &)> write)
Combined button and popup list for selecting options.