1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2000 Stephan Kulow <coolo@kde.org>
4 SPDX-FileCopyrightText: 2000-2009 David Faure <faure@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8
9#include "mkpathjob.h"
10#include "../utils_p.h"
11#include "job_p.h"
12#include "mkdirjob.h"
13
14#include <QFileInfo>
15#include <QTimer>
16
17using namespace KIO;
18
19class KIO::MkpathJobPrivate : public KIO::JobPrivate
20{
21public:
22 MkpathJobPrivate(const QUrl &url, const QUrl &baseUrl, JobFlags flags)
23 : JobPrivate()
24 , m_url(url)
25 , m_pathComponents(url.path().split(sep: QLatin1Char('/'), behavior: Qt::SkipEmptyParts))
26 , m_pathIterator()
27 , m_flags(flags)
28 {
29 const QStringList basePathComponents = baseUrl.path().split(sep: QLatin1Char('/'), behavior: Qt::SkipEmptyParts);
30
31#ifdef Q_OS_WIN
32 const QString startPath;
33#else
34 const QString startPath = QLatin1String("/");
35#endif
36 m_url.setPath(path: startPath);
37 int i = 0;
38 for (; i < basePathComponents.count() && i < m_pathComponents.count(); ++i) {
39 const QString pathComponent = m_pathComponents.at(i);
40 if (pathComponent == basePathComponents.at(i)) {
41 m_url.setPath(path: Utils::concatPaths(path1: m_url.path(), path2: pathComponent));
42 } else {
43 break;
44 }
45 }
46 if (i > 0) {
47 m_pathComponents.erase(abegin: m_pathComponents.begin(), aend: m_pathComponents.begin() + i);
48 }
49
50 // fast path for local files using QFileInfo::isDir
51 if (m_url.isLocalFile()) {
52 i = 0;
53 for (; i < m_pathComponents.count(); ++i) {
54 const QString localFile = m_url.toLocalFile();
55 QString testDir;
56 if (localFile == startPath) {
57 testDir = localFile + m_pathComponents.at(i);
58 } else {
59 testDir = localFile + QLatin1Char('/') + m_pathComponents.at(i);
60 }
61 if (QFileInfo(testDir).isDir()) {
62 m_url.setPath(path: testDir);
63 } else {
64 break;
65 }
66 }
67 if (i > 0) {
68 m_pathComponents.erase(abegin: m_pathComponents.begin(), aend: m_pathComponents.begin() + i);
69 }
70 }
71
72 m_pathIterator = m_pathComponents.constBegin();
73 }
74
75 QUrl m_url;
76 QUrl m_baseUrl;
77 QStringList m_pathComponents;
78 QStringList::const_iterator m_pathIterator;
79 const JobFlags m_flags;
80 Q_DECLARE_PUBLIC(MkpathJob)
81
82 void slotStart();
83
84 static inline MkpathJob *newJob(const QUrl &url, const QUrl &baseUrl, JobFlags flags)
85 {
86 MkpathJob *job = new MkpathJob(*new MkpathJobPrivate(url, baseUrl, flags));
87 job->setUiDelegate(KIO::createDefaultJobUiDelegate());
88 if (!(flags & HideProgressInfo)) {
89 KIO::getJobTracker()->registerJob(job);
90 }
91 if (!(flags & NoPrivilegeExecution)) {
92 job->d_func()->m_privilegeExecutionEnabled = true;
93 job->d_func()->m_operationType = MkDir;
94 }
95 return job;
96 }
97};
98
99MkpathJob::MkpathJob(MkpathJobPrivate &dd)
100 : Job(dd)
101{
102 Q_D(MkpathJob);
103 QTimer::singleShot(interval: 0, receiver: this, slot: [d]() {
104 d->slotStart();
105 });
106}
107
108MkpathJob::~MkpathJob()
109{
110}
111
112void MkpathJobPrivate::slotStart()
113{
114 Q_Q(MkpathJob);
115
116 if (m_pathIterator == m_pathComponents.constBegin()) { // first time: emit total
117 q->setTotalAmount(unit: KJob::Directories, amount: m_pathComponents.count());
118 }
119
120 if (m_pathIterator != m_pathComponents.constEnd()) {
121 m_url.setPath(path: Utils::concatPaths(path1: m_url.path(), path2: *m_pathIterator));
122 KIO::Job *job = KIO::mkdir(url: m_url);
123 job->setParentJob(q);
124 q->addSubjob(job);
125 q->setProcessedAmount(unit: KJob::Directories, amount: q->processedAmount(unit: KJob::Directories) + 1);
126 } else {
127 q->emitResult();
128 }
129}
130
131void MkpathJob::slotResult(KJob *job)
132{
133 Q_D(MkpathJob);
134 if (job->error() && job->error() != KIO::ERR_DIR_ALREADY_EXIST) {
135 KIO::Job::slotResult(job); // will set the error and emit result(this)
136 return;
137 }
138 removeSubjob(job);
139
140 Q_EMIT directoryCreated(url: d->m_url);
141
142 // Move on to next one
143 ++d->m_pathIterator;
144 emitPercent(processedAmount: d->m_pathIterator - d->m_pathComponents.constBegin(), totalAmount: d->m_pathComponents.count());
145 d->slotStart();
146}
147
148MkpathJob *KIO::mkpath(const QUrl &url, const QUrl &baseUrl, KIO::JobFlags flags)
149{
150 return MkpathJobPrivate::newJob(url, baseUrl, flags);
151}
152
153#include "moc_mkpathjob.cpp"
154

source code of kio/src/core/mkpathjob.cpp