/* This file is part of the KDE libraries SPDX-FileCopyrightText: 2000 Stephan Kulow SPDX-FileCopyrightText: 2000-2009 David Faure SPDX-License-Identifier: LGPL-2.0-or-later */ #include "mkpathjob.h" #include "../utils_p.h" #include "job_p.h" #include "mkdirjob.h" #include #include using namespace KIO; class KIO::MkpathJobPrivate : public KIO::JobPrivate { public: MkpathJobPrivate(const QUrl &url, const QUrl &baseUrl, JobFlags flags) : JobPrivate() , m_url(url) , m_pathComponents(url.path().split(QLatin1Char('/'), Qt::SkipEmptyParts)) , m_pathIterator() , m_flags(flags) { const QStringList basePathComponents = baseUrl.path().split(QLatin1Char('/'), Qt::SkipEmptyParts); #ifdef Q_OS_WIN const QString startPath; #else const QString startPath = QLatin1String("/"); #endif m_url.setPath(startPath); int i = 0; for (; i < basePathComponents.count() && i < m_pathComponents.count(); ++i) { const QString pathComponent = m_pathComponents.at(i); if (pathComponent == basePathComponents.at(i)) { m_url.setPath(Utils::concatPaths(m_url.path(), pathComponent)); } else { break; } } if (i > 0) { m_pathComponents.erase(m_pathComponents.begin(), m_pathComponents.begin() + i); } // fast path for local files using QFileInfo::isDir if (m_url.isLocalFile()) { i = 0; for (; i < m_pathComponents.count(); ++i) { const QString localFile = m_url.toLocalFile(); QString testDir; if (localFile == startPath) { testDir = localFile + m_pathComponents.at(i); } else { testDir = localFile + QLatin1Char('/') + m_pathComponents.at(i); } if (QFileInfo(testDir).isDir()) { m_url.setPath(testDir); } else { break; } } if (i > 0) { m_pathComponents.erase(m_pathComponents.begin(), m_pathComponents.begin() + i); } } m_pathIterator = m_pathComponents.constBegin(); } QUrl m_url; QUrl m_baseUrl; QStringList m_pathComponents; QStringList::const_iterator m_pathIterator; const JobFlags m_flags; Q_DECLARE_PUBLIC(MkpathJob) void slotStart(); static inline MkpathJob *newJob(const QUrl &url, const QUrl &baseUrl, JobFlags flags) { MkpathJob *job = new MkpathJob(*new MkpathJobPrivate(url, baseUrl, flags)); job->setUiDelegate(KIO::createDefaultJobUiDelegate()); if (!(flags & HideProgressInfo)) { KIO::getJobTracker()->registerJob(job); } if (!(flags & NoPrivilegeExecution)) { job->d_func()->m_privilegeExecutionEnabled = true; job->d_func()->m_operationType = MkDir; } return job; } }; MkpathJob::MkpathJob(MkpathJobPrivate &dd) : Job(dd) { Q_D(MkpathJob); QTimer::singleShot(0, this, [d]() { d->slotStart(); }); } MkpathJob::~MkpathJob() { } void MkpathJobPrivate::slotStart() { Q_Q(MkpathJob); if (m_pathIterator == m_pathComponents.constBegin()) { // first time: emit total q->setTotalAmount(KJob::Directories, m_pathComponents.count()); } if (m_pathIterator != m_pathComponents.constEnd()) { m_url.setPath(Utils::concatPaths(m_url.path(), *m_pathIterator)); KIO::Job *job = KIO::mkdir(m_url); job->setParentJob(q); q->addSubjob(job); q->setProcessedAmount(KJob::Directories, q->processedAmount(KJob::Directories) + 1); } else { q->emitResult(); } } void MkpathJob::slotResult(KJob *job) { Q_D(MkpathJob); if (job->error() && job->error() != KIO::ERR_DIR_ALREADY_EXIST) { KIO::Job::slotResult(job); // will set the error and emit result(this) return; } removeSubjob(job); Q_EMIT directoryCreated(d->m_url); // Move on to next one ++d->m_pathIterator; emitPercent(d->m_pathIterator - d->m_pathComponents.constBegin(), d->m_pathComponents.count()); d->slotStart(); } MkpathJob *KIO::mkpath(const QUrl &url, const QUrl &baseUrl, KIO::JobFlags flags) { return MkpathJobPrivate::newJob(url, baseUrl, flags); } #include "moc_mkpathjob.cpp"