KIO

filecopyjob.cpp
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 "filecopyjob.h"
10#include "askuseractioninterface.h"
11#include "job_p.h"
12#include "kprotocolmanager.h"
13#include "scheduler.h"
14#include "worker_p.h"
15#include <kio/jobuidelegatefactory.h>
16
17#include <KLocalizedString>
18
19#include <QFile>
20#include <QTimer>
21
22using namespace KIO;
23
24static inline Worker *jobWorker(SimpleJob *job)
25{
26 return SimpleJobPrivate::get(job)->m_worker;
27}
28
29/** @internal */
30class KIO::FileCopyJobPrivate : public KIO::JobPrivate
31{
32public:
33 FileCopyJobPrivate(const QUrl &src, const QUrl &dest, int permissions, bool move, JobFlags flags)
34 : m_sourceSize(filesize_t(-1))
35 , m_src(src)
36 , m_dest(dest)
37 , m_moveJob(nullptr)
38 , m_copyJob(nullptr)
39 , m_delJob(nullptr)
40 , m_chmodJob(nullptr)
41 , m_getJob(nullptr)
42 , m_putJob(nullptr)
43 , m_permissions(permissions)
44 , m_move(move)
45 , m_mustChmod(0)
46 , m_bFileCopyInProgress(false)
47 , m_flags(flags)
48 {
49 }
50 KIO::filesize_t m_sourceSize;
51 QDateTime m_modificationTime;
52 QUrl m_src;
53 QUrl m_dest;
54 QByteArray m_buffer;
55 SimpleJob *m_moveJob;
56 SimpleJob *m_copyJob;
57 SimpleJob *m_delJob;
58 SimpleJob *m_chmodJob;
59 TransferJob *m_getJob;
60 TransferJob *m_putJob;
61 int m_permissions;
62 bool m_move : 1;
63 bool m_canResume : 1;
64 bool m_resumeAnswerSent : 1;
65 bool m_mustChmod : 1;
66 bool m_bFileCopyInProgress : 1;
67 JobFlags m_flags;
68
69 void startBestCopyMethod();
70 void startCopyJob();
71 void startCopyJob(const QUrl &workerUrl);
72 void startRenameJob(const QUrl &workerUrl);
73 void startDataPump();
74 void connectSubjob(SimpleJob *job);
75
76 void slotStart();
77 void slotData(KIO::Job *, const QByteArray &data);
78 void slotDataReq(KIO::Job *, QByteArray &data);
79 void slotMimetype(KIO::Job *, const QString &type);
80 /**
81 * Forward signal from subjob
82 * @param job the job that emitted this signal
83 * @param offset the offset to resume from
84 */
85 void slotCanResume(KIO::Job *job, KIO::filesize_t offset);
86 void processCanResumeResult(KIO::Job *job, RenameDialog_Result result, KIO::filesize_t offset);
87
88 Q_DECLARE_PUBLIC(FileCopyJob)
89
90 static inline FileCopyJob *newJob(const QUrl &src, const QUrl &dest, int permissions, bool move, JobFlags flags)
91 {
92 // qDebug() << src << "->" << dest;
93 FileCopyJob *job = new FileCopyJob(*new FileCopyJobPrivate(src, dest, permissions, move, flags));
94 job->setProperty("destUrl", dest.toString());
96 if (!(flags & HideProgressInfo)) {
98 }
99 if (!(flags & NoPrivilegeExecution)) {
100 job->d_func()->m_privilegeExecutionEnabled = true;
101 job->d_func()->m_operationType = move ? Move : Copy;
102 }
103 return job;
104 }
105};
106
107static bool isSrcDestSameWorkerProcess(const QUrl &src, const QUrl &dest)
108{
109 /* clang-format off */
110 return src.scheme() == dest.scheme()
111 && src.host() == dest.host()
112 && src.port() == dest.port()
113 && src.userName() == dest.userName()
114 && src.password() == dest.password();
115 /* clang-format on */
116}
117
118/*
119 * The FileCopyJob works according to the famous Bavarian
120 * 'Alternating Bitburger Protocol': we either drink a beer or we
121 * we order a beer, but never both at the same time.
122 * Translated to KIO workers: We alternate between receiving a block of data
123 * and sending it away.
124 */
125FileCopyJob::FileCopyJob(FileCopyJobPrivate &dd)
126 : Job(dd)
127{
129 QTimer::singleShot(0, this, [d]() {
130 d->slotStart();
131 });
132}
133
134void FileCopyJobPrivate::slotStart()
135{
136 Q_Q(FileCopyJob);
137 if (!m_move) {
138 JobPrivate::emitCopying(q, m_src, m_dest);
139 } else {
140 JobPrivate::emitMoving(q, m_src, m_dest);
141 }
142
143 if (m_move) {
144 // The if() below must be the same as the one in startBestCopyMethod
145 if (isSrcDestSameWorkerProcess(m_src, m_dest)) {
146 startRenameJob(m_src);
147 return;
148 } else if (m_src.isLocalFile() && KProtocolManager::canRenameFromFile(m_dest)) {
149 startRenameJob(m_dest);
150 return;
151 } else if (m_dest.isLocalFile() && KProtocolManager::canRenameToFile(m_src)) {
152 startRenameJob(m_src);
153 return;
154 }
155 // No fast-move available, use copy + del.
156 }
157 startBestCopyMethod();
158}
159
160void FileCopyJobPrivate::startBestCopyMethod()
161{
162 if (isSrcDestSameWorkerProcess(m_src, m_dest)) {
163 startCopyJob();
164 } else if (m_src.isLocalFile() && KProtocolManager::canCopyFromFile(m_dest)) {
165 startCopyJob(m_dest);
166 } else if (m_dest.isLocalFile() && KProtocolManager::canCopyToFile(m_src) && !KIO::Scheduler::isWorkerOnHoldFor(m_src)) {
167 startCopyJob(m_src);
168 } else {
169 startDataPump();
170 }
171}
172
173FileCopyJob::~FileCopyJob()
174{
175}
176
178{
180 d->m_sourceSize = size;
181 if (size != (KIO::filesize_t)-1) {
183 }
184}
185
187{
189 d->m_modificationTime = mtime;
190}
191
193{
194 return d_func()->m_src;
195}
196
198{
199 return d_func()->m_dest;
200}
201
202void FileCopyJobPrivate::startCopyJob()
203{
204 startCopyJob(m_src);
205}
206
207void FileCopyJobPrivate::startCopyJob(const QUrl &workerUrl)
208{
209 Q_Q(FileCopyJob);
210 // qDebug();
211 KIO_ARGS << m_src << m_dest << m_permissions << (qint8)(m_flags & Overwrite);
212 auto job = new DirectCopyJob(workerUrl, packedArgs);
213 m_copyJob = job;
214 m_copyJob->setParentJob(q);
215 if (m_modificationTime.isValid()) {
216 m_copyJob->addMetaData(QStringLiteral("modified"), m_modificationTime.toString(Qt::ISODate)); // #55804
217 }
218 q->addSubjob(m_copyJob);
219 connectSubjob(m_copyJob);
220 q->connect(job, &DirectCopyJob::canResume, q, [this](KIO::Job *job, KIO::filesize_t offset) {
221 slotCanResume(job, offset);
222 });
223}
224
225void FileCopyJobPrivate::startRenameJob(const QUrl &workerUrl)
226{
227 Q_Q(FileCopyJob);
228 m_mustChmod = true; // CMD_RENAME by itself doesn't change permissions
229 KIO_ARGS << m_src << m_dest << (qint8)(m_flags & Overwrite);
230 m_moveJob = SimpleJobPrivate::newJobNoUi(workerUrl, CMD_RENAME, packedArgs);
231 m_moveJob->setParentJob(q);
232 if (m_modificationTime.isValid()) {
233 m_moveJob->addMetaData(QStringLiteral("modified"), m_modificationTime.toString(Qt::ISODate)); // #55804
234 }
235 q->addSubjob(m_moveJob);
236 connectSubjob(m_moveJob);
237}
238
239void FileCopyJobPrivate::connectSubjob(SimpleJob *job)
240{
241 Q_Q(FileCopyJob);
242 q->connect(job, &KJob::totalSize, q, [q](KJob *job, qulonglong totalSize) {
243 Q_UNUSED(job);
244 if (totalSize != q->totalAmount(KJob::Bytes)) {
245 q->setTotalAmount(KJob::Bytes, totalSize);
246 }
247 });
248
249 q->connect(job, &KJob::processedSize, q, [q, this](const KJob *job, qulonglong processedSize) {
250 if (job == m_copyJob) {
251 m_bFileCopyInProgress = processedSize > 0;
252 }
253 q->setProcessedAmount(KJob::Bytes, processedSize);
254 });
255
256 q->connect(job, &KJob::percentChanged, q, [q](KJob *, ulong percent) {
257 if (percent > q->percent()) {
258 q->setPercent(percent);
259 }
260 });
261
262 if (q->isSuspended()) {
263 job->suspend();
264 }
265}
266
267bool FileCopyJob::doSuspend()
268{
270 if (d->m_moveJob) {
271 d->m_moveJob->suspend();
272 }
273
274 if (d->m_copyJob) {
275 d->m_copyJob->suspend();
276 }
277
278 if (d->m_getJob) {
279 d->m_getJob->suspend();
280 }
281
282 if (d->m_putJob) {
283 d->m_putJob->suspend();
284 }
285
287 return true;
288}
289
290bool FileCopyJob::doResume()
291{
293 if (d->m_moveJob) {
294 d->m_moveJob->resume();
295 }
296
297 if (d->m_copyJob) {
298 d->m_copyJob->resume();
299 }
300
301 if (d->m_getJob) {
302 d->m_getJob->resume();
303 }
304
305 if (d->m_putJob) {
306 d->m_putJob->resume();
307 }
308
310 return true;
311}
312
313void FileCopyJobPrivate::startDataPump()
314{
315 Q_Q(FileCopyJob);
316 // qDebug();
317
318 m_canResume = false;
319 m_resumeAnswerSent = false;
320 m_getJob = nullptr; // for now
321 m_putJob = put(m_dest, m_permissions, (m_flags | HideProgressInfo) /* no GUI */);
322 m_putJob->setParentJob(q);
323 // qDebug() << "m_putJob=" << m_putJob << "m_dest=" << m_dest;
324 if (m_modificationTime.isValid()) {
325 m_putJob->setModificationTime(m_modificationTime);
326 }
327
328 // The first thing the put job will tell us is whether we can
329 // resume or not (this is always emitted)
330 q->connect(m_putJob, &KIO::TransferJob::canResume, q, [this](KIO::Job *job, KIO::filesize_t offset) {
331 slotCanResume(job, offset);
332 });
333 q->connect(m_putJob, &KIO::TransferJob::dataReq, q, [this](KIO::Job *job, QByteArray &data) {
334 slotDataReq(job, data);
335 });
336 q->addSubjob(m_putJob);
337}
338
339void FileCopyJobPrivate::slotCanResume(KIO::Job *job, KIO::filesize_t offset)
340{
341 Q_Q(FileCopyJob);
342
343 if (job == m_getJob) {
344 // Cool, the get job said ok, we can resume
345 m_canResume = true;
346 // qDebug() << "'can resume' from the GET job -> we can resume";
347
348 jobWorker(m_getJob)->setOffset(jobWorker(m_putJob)->offset());
349 return;
350 }
351
352 if (job == m_putJob || job == m_copyJob) {
353 // qDebug() << "'can resume' from PUT job. offset=" << KIO::number(offset);
354 if (offset == 0) {
355 m_resumeAnswerSent = true; // No need for an answer
356 } else {
357 KIO::Job *kioJob = q->parentJob() ? q->parentJob() : q;
358 auto *askUserActionInterface = KIO::delegateExtension<KIO::AskUserActionInterface *>(kioJob);
359 if (!KProtocolManager::autoResume() && !(m_flags & Overwrite) && askUserActionInterface) {
361
362 q->connect(askUserActionInterface, renameSignal, q, [=, this](KIO::RenameDialog_Result result, const QUrl &, const KJob *askJob) {
363 Q_ASSERT(kioJob == askJob);
364
365 // Only receive askUserRenameResult once per rename dialog
366 QObject::disconnect(askUserActionInterface, renameSignal, q, nullptr);
367
368 processCanResumeResult(job, result, offset);
369 });
370
371 // Ask confirmation about resuming previous transfer
372 askUserActionInterface->askUserRename(kioJob,
373 i18n("File Already Exists"),
374 m_src,
375 m_dest,
377 m_sourceSize,
378 offset);
379 return;
380 }
381 }
382
383 processCanResumeResult(job, //
384 Result_Resume, // The default is to resume
385 offset);
386
387 return;
388 }
389
390 qCWarning(KIO_CORE) << "unknown job=" << job << "m_getJob=" << m_getJob << "m_putJob=" << m_putJob;
391}
392
393void FileCopyJobPrivate::processCanResumeResult(KIO::Job *job, RenameDialog_Result result, KIO::filesize_t offset)
394{
395 Q_Q(FileCopyJob);
396 if (result == Result_Overwrite || (m_flags & Overwrite)) {
397 offset = 0;
398 } else if (result == Result_Cancel) {
399 if (job == m_putJob) {
400 m_putJob->kill(FileCopyJob::Quietly);
401 q->removeSubjob(m_putJob);
402 m_putJob = nullptr;
403 } else {
404 m_copyJob->kill(FileCopyJob::Quietly);
405 q->removeSubjob(m_copyJob);
406 m_copyJob = nullptr;
407 }
408 q->setError(ERR_USER_CANCELED);
409 q->emitResult();
410 return;
411 }
412
413 if (job == m_copyJob) {
414 jobWorker(m_copyJob)->sendResumeAnswer(offset != 0);
415 return;
416 }
417
418 if (job == m_putJob) {
419 m_getJob = KIO::get(m_src, NoReload, HideProgressInfo /* no GUI */);
420 m_getJob->setParentJob(q);
421 // qDebug() << "m_getJob=" << m_getJob << m_src;
422 m_getJob->addMetaData(QStringLiteral("AllowCompressedPage"), QStringLiteral("false"));
423 // Set size in subjob. This helps if the worker doesn't emit totalSize.
424 if (m_sourceSize != (KIO::filesize_t)-1) {
425 m_getJob->setTotalAmount(KJob::Bytes, m_sourceSize);
426 }
427
428 if (offset) {
429 // qDebug() << "Setting metadata for resume to" << (unsigned long) offset;
430 m_getJob->addMetaData(QStringLiteral("range-start"), KIO::number(offset));
431
432 // Might or might not get emitted
433 q->connect(m_getJob, &KIO::TransferJob::canResume, q, [this](KIO::Job *job, KIO::filesize_t offset) {
434 slotCanResume(job, offset);
435 });
436 }
437 jobWorker(m_putJob)->setOffset(offset);
438
439 m_putJob->d_func()->internalSuspend();
440 q->addSubjob(m_getJob);
441 connectSubjob(m_getJob); // Progress info depends on get
442 m_getJob->d_func()->internalResume(); // Order a beer
443
444 q->connect(m_getJob, &KIO::TransferJob::data, q, [this](KIO::Job *job, const QByteArray &data) {
445 slotData(job, data);
446 });
447 q->connect(m_getJob, &KIO::TransferJob::mimeTypeFound, q, [this](KIO::Job *job, const QString &type) {
448 slotMimetype(job, type);
449 });
450 }
451}
452
453void FileCopyJobPrivate::slotData(KIO::Job *, const QByteArray &data)
454{
455 // qDebug() << "data size:" << data.size();
456 Q_ASSERT(m_putJob);
457 if (!m_putJob) {
458 return; // Don't crash
459 }
460 m_getJob->d_func()->internalSuspend();
461 m_putJob->d_func()->internalResume(); // Drink the beer
462 m_buffer += data;
463
464 // On the first set of data incoming, we tell the "put" worker about our
465 // decision about resuming
466 if (!m_resumeAnswerSent) {
467 m_resumeAnswerSent = true;
468 // qDebug() << "(first time) -> send resume answer " << m_canResume;
469 jobWorker(m_putJob)->sendResumeAnswer(m_canResume);
470 }
471}
472
473void FileCopyJobPrivate::slotDataReq(KIO::Job *, QByteArray &data)
474{
475 Q_Q(FileCopyJob);
476 // qDebug();
477 if (!m_resumeAnswerSent && !m_getJob) {
478 // This can't happen
479 q->setError(ERR_INTERNAL);
480 q->setErrorText(QStringLiteral("'Put' job did not send canResume or 'Get' job did not send data!"));
481 m_putJob->kill(FileCopyJob::Quietly);
482 q->removeSubjob(m_putJob);
483 m_putJob = nullptr;
484 q->emitResult();
485 return;
486 }
487 if (m_getJob) {
488 m_getJob->d_func()->internalResume(); // Order more beer
489 m_putJob->d_func()->internalSuspend();
490 }
491 data = m_buffer;
492 m_buffer = QByteArray();
493}
494
495void FileCopyJobPrivate::slotMimetype(KIO::Job *, const QString &type)
496{
497 Q_Q(FileCopyJob);
498 Q_EMIT q->mimeTypeFound(q, type);
499}
500
502{
504 // qDebug() << "this=" << this << "job=" << job;
505 removeSubjob(job);
506
507 // If result comes from copyjob then we are not writing anymore.
508 if (job == d->m_copyJob) {
509 d->m_bFileCopyInProgress = false;
510 }
511
512 // Did job have an error ?
513 if (job->error()) {
514 if ((job == d->m_moveJob) && (job->error() == ERR_UNSUPPORTED_ACTION)) {
515 d->m_moveJob = nullptr;
516 d->startBestCopyMethod();
517 return;
518 } else if ((job == d->m_copyJob) && (job->error() == ERR_UNSUPPORTED_ACTION)) {
519 d->m_copyJob = nullptr;
520 d->startDataPump();
521 return;
522 } else if (job == d->m_getJob) {
523 d->m_getJob = nullptr;
524 if (d->m_putJob) {
525 d->m_putJob->kill(Quietly);
526 removeSubjob(d->m_putJob);
527 }
528 } else if (job == d->m_putJob) {
529 d->m_putJob = nullptr;
530 if (d->m_getJob) {
531 d->m_getJob->kill(Quietly);
532 removeSubjob(d->m_getJob);
533 }
534 } else if (job == d->m_chmodJob) {
535 d->m_chmodJob = nullptr;
536 if (d->m_delJob) {
537 d->m_delJob->kill(Quietly);
538 removeSubjob(d->m_delJob);
539 }
540 } else if (job == d->m_delJob) {
541 d->m_delJob = nullptr;
542 if (d->m_chmodJob) {
543 d->m_chmodJob->kill(Quietly);
544 removeSubjob(d->m_chmodJob);
545 }
546 }
547 setError(job->error());
548 setErrorText(job->errorText());
549 emitResult();
550 return;
551 }
552
553 if (d->m_mustChmod) {
554 // If d->m_permissions == -1, keep the default permissions
555 if (d->m_permissions != -1) {
556 d->m_chmodJob = chmod(d->m_dest, d->m_permissions);
557 addSubjob(d->m_chmodJob);
558 }
559 d->m_mustChmod = false;
560 }
561
562 if (job == d->m_moveJob) {
563 d->m_moveJob = nullptr; // Finished
564 }
565
566 if (job == d->m_copyJob) {
567 d->m_copyJob = nullptr;
568 if (d->m_move) {
569 d->m_delJob = file_delete(d->m_src, HideProgressInfo /*no GUI*/); // Delete source
570 addSubjob(d->m_delJob);
571 }
572 }
573
574 if (job == d->m_getJob) {
575 // qDebug() << "m_getJob finished";
576 d->m_getJob = nullptr; // No action required
577 if (d->m_putJob) {
578 d->m_putJob->d_func()->internalResume();
579 }
580 }
581
582 if (job == d->m_putJob) {
583 // qDebug() << "m_putJob finished";
584 d->m_putJob = nullptr;
585 if (d->m_getJob) {
586 // The get job is still running, probably after emitting data(QByteArray())
587 // and before we receive its finished().
588 d->m_getJob->d_func()->internalResume();
589 }
590 if (d->m_move) {
591 d->m_delJob = file_delete(d->m_src, HideProgressInfo /*no GUI*/); // Delete source
592 addSubjob(d->m_delJob);
593 }
594 }
595
596 if (job == d->m_delJob) {
597 d->m_delJob = nullptr; // Finished
598 }
599
600 if (job == d->m_chmodJob) {
601 d->m_chmodJob = nullptr; // Finished
602 }
603
604 if (!hasSubjobs()) {
605 emitResult();
606 }
607}
608
609bool FileCopyJob::doKill()
610{
611#ifdef Q_OS_WIN
612 // TODO Use SetConsoleCtrlHandler on Windows or similar behaviour.
613 // https://stackoverflow.com/questions/2007516/is-there-a-posix-sigterm-alternative-on-windows-a-gentle-kill-for-console-ap
614 // https://danielkaes.wordpress.com/2009/06/04/how-to-catch-kill-events-with-python/
615 // https://phabricator.kde.org/D25117#566107
616
618
619 // If we are interrupted in the middle of file copying,
620 // we may end up with corrupted file at the destination.
621 // It is better to clean up this file. If a copy is being
622 // made as part of move operation then delete the dest only if
623 // source file is intact (m_delJob == NULL).
624 if (d->m_bFileCopyInProgress && d->m_copyJob && d->m_dest.isLocalFile()) {
625 if (d->m_flags & Overwrite) {
626 QFile::remove(d->m_dest.toLocalFile() + QStringLiteral(".part"));
627 } else {
628 QFile::remove(d->m_dest.toLocalFile());
629 }
630 }
631#endif
632 return Job::doKill();
633}
634
635FileCopyJob *KIO::file_copy(const QUrl &src, const QUrl &dest, int permissions, JobFlags flags)
636{
637 return FileCopyJobPrivate::newJob(src, dest, permissions, false, flags);
638}
639
640FileCopyJob *KIO::file_move(const QUrl &src, const QUrl &dest, int permissions, JobFlags flags)
641{
642 FileCopyJob *job = FileCopyJobPrivate::newJob(src, dest, permissions, true, flags);
643 if (job->uiDelegateExtension()) {
644 job->uiDelegateExtension()->createClipboardUpdater(job, JobUiDelegateExtension::UpdateContent);
645 }
646 return job;
647}
648
649#include "moc_filecopyjob.cpp"
bool hasSubjobs() const
void askUserRenameResult(KIO::RenameDialog_Result result, const QUrl &newUrl, KJob *parentJob)
Implementations of this interface must emit this signal when the rename dialog finishes,...
The FileCopyJob copies data from one place to another.
QUrl destUrl() const
Returns the destination URL.
void setModificationTime(const QDateTime &mtime)
Sets the modification time of the file.
void slotResult(KJob *job) override
Called whenever a subjob finishes.
void setSourceSize(KIO::filesize_t size)
If you know the size of the source file, call this method to inform this job.
QUrl srcUrl() const
Returns the source URL.
virtual ClipboardUpdater * createClipboardUpdater(Job *job, ClipboardUpdaterMode mode)
Creates a clipboard updater as a child of the given job.
The base class for all jobs.
bool doKill() override
Abort this job.
Definition job.cpp:157
void setParentJob(Job *parentJob)
Set the parent Job.
Definition job.cpp:192
Job * parentJob() const
Returns the parent job, if there is one.
Definition job.cpp:200
JobUiDelegateExtension * uiDelegateExtension() const
Retrieves the UI delegate extension used by this job.
Definition job.cpp:44
bool removeSubjob(KJob *job) override
Mark a sub job as being done.
Definition job.cpp:80
bool doSuspend() override
Suspend this job.
Definition job.cpp:168
bool doResume() override
Resume this job.
Definition job.cpp:179
bool addSubjob(KJob *job) override
Add a job that has to be finished before a result is emitted.
Definition job.cpp:56
void addMetaData(const QString &key, const QString &value)
Add key/value pair to the meta data that is sent to the worker.
Definition job.cpp:221
A simple job (one url and one command).
The transfer job pumps data into and/or out of a KIO worker.
void mimeTypeFound(KIO::Job *job, const QString &mimeType)
MIME type determined.
void dataReq(KIO::Job *job, QByteArray &data)
Request for data.
void data(KIO::Job *job, const QByteArray &data)
Data from the worker has arrived.
void setModificationTime(const QDateTime &mtime)
Sets the modification time of the file to be created (by KIO::put) Note that some KIO workers might i...
void canResume(KIO::Job *job, KIO::filesize_t offset)
virtual void registerJob(KJob *job)
void setErrorText(const QString &errorText)
bool suspend()
void setTotalAmount(Unit unit, qulonglong amount)
void emitResult()
int error() const
void processedSize(KJob *job, qulonglong size)
void setError(int errorCode)
void totalSize(KJob *job, qulonglong size)
QString errorText() const
bool kill(KJob::KillVerbosity verbosity=KJob::Quietly)
void setUiDelegate(KJobUiDelegate *delegate)
void percentChanged(KJob *job, unsigned long percent)
static bool canRenameToFile(const QUrl &url)
Returns whether the protocol can rename (i.e.
static bool canCopyFromFile(const QUrl &url)
Returns whether the protocol can copy files/objects directly from the filesystem itself.
static bool canRenameFromFile(const QUrl &url)
Returns whether the protocol can rename (i.e.
static bool autoResume()
Returns true if partial downloads should be automatically resumed.
static bool canCopyToFile(const QUrl &url)
Returns whether the protocol can copy files/objects directly to the filesystem itself.
QString i18n(const char *text, const TYPE &arg...)
A namespace for KIO globals.
KIOCORE_EXPORT ChmodJob * chmod(const KFileItemList &lstItems, int permissions, int mask, const QString &newOwner, const QString &newGroup, bool recursive, JobFlags flags=DefaultFlags)
Creates a job that changes permissions/ownership on several files or directories, optionally recursiv...
Definition chmodjob.cpp:288
@ RenameDialog_Resume
Offer a "Resume" button (plus "Resume All" if RenameDialog_MultipleItems).
@ RenameDialog_NoRename
Don't offer a "Rename" button.
@ RenameDialog_Overwrite
We have an existing destination, show details about it and offer to overwrite it.
KIOCORE_EXPORT CopyJob * move(const QUrl &src, const QUrl &dest, JobFlags flags=DefaultFlags)
Moves a file or directory src to the given destination dest.
Definition copyjob.cpp:2657
KIOCORE_EXPORT QString number(KIO::filesize_t size)
Converts a size to a string representation Not unlike QString::number(...)
Definition global.cpp:55
KIOCORE_EXPORT SimpleJob * file_delete(const QUrl &src, JobFlags flags=DefaultFlags)
Delete a single file.
Definition job.cpp:373
T delegateExtension(KJob *job)
Returns the child of the job's uiDelegate() that implements the given extension, or nullptr if none w...
RenameDialog_Result
The result of a rename or skip dialog.
KIOCORE_EXPORT KJobUiDelegate * createDefaultJobUiDelegate()
Convenience method: use default factory, if there's one, to create a delegate and return it.
QFlags< RenameDialog_Option > RenameDialog_Options
Stores a combination of RenameDialog_Option values.
KIOCORE_EXPORT TransferJob * get(const QUrl &url, LoadType reload=NoReload, JobFlags flags=DefaultFlags)
Get (means: read).
KIOCORE_EXPORT FileCopyJob * file_move(const QUrl &src, const QUrl &dest, int permissions=-1, JobFlags flags=DefaultFlags)
Move a single file.
KIOCORE_EXPORT FileCopyJob * file_copy(const QUrl &src, const QUrl &dest, int permissions=-1, JobFlags flags=DefaultFlags)
Copy a single file.
@ HideProgressInfo
Hide progress information dialog, i.e. don't show a GUI.
Definition job_base.h:251
@ Overwrite
When set, automatically overwrite the destination if it exists already.
Definition job_base.h:267
@ NoPrivilegeExecution
When set, notifies the worker that application/job does not want privilege execution.
Definition job_base.h:276
KIOCORE_EXPORT TransferJob * put(const QUrl &url, int permissions, JobFlags flags=DefaultFlags)
Put (means: write)
qulonglong filesize_t
64-bit file size
Definition global.h:35
KIOCORE_EXPORT KJobTrackerInterface * getJobTracker()
Returns the job tracker to be used by all KIO jobs (in which HideProgressInfo is not set)
bool isValid() const const
QString toString(QStringView format, QCalendar cal) const const
bool remove()
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
bool setProperty(const char *name, QVariant &&value)
QString host(ComponentFormattingOptions options) const const
bool isLocalFile() const const
QString password(ComponentFormattingOptions options) const const
int port(int defaultPort) const const
QString scheme() const const
QString toString(FormattingOptions options) const const
QString userName(ComponentFormattingOptions options) const const
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 16:58:45 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.