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("errorPage"), QStringLiteral("false"));
423 m_getJob->addMetaData(QStringLiteral("AllowCompressedPage"), QStringLiteral("false"));
424 // Set size in subjob. This helps if the worker doesn't emit totalSize.
425 if (m_sourceSize != (KIO::filesize_t)-1) {
426 m_getJob->setTotalAmount(KJob::Bytes, m_sourceSize);
427 }
428
429 if (offset) {
430 // qDebug() << "Setting metadata for resume to" << (unsigned long) offset;
431 m_getJob->addMetaData(QStringLiteral("range-start"), KIO::number(offset));
432
433 // Might or might not get emitted
434 q->connect(m_getJob, &KIO::TransferJob::canResume, q, [this](KIO::Job *job, KIO::filesize_t offset) {
435 slotCanResume(job, offset);
436 });
437 }
438 jobWorker(m_putJob)->setOffset(offset);
439
440 m_putJob->d_func()->internalSuspend();
441 q->addSubjob(m_getJob);
442 connectSubjob(m_getJob); // Progress info depends on get
443 m_getJob->d_func()->internalResume(); // Order a beer
444
445 q->connect(m_getJob, &KIO::TransferJob::data, q, [this](KIO::Job *job, const QByteArray &data) {
446 slotData(job, data);
447 });
448 q->connect(m_getJob, &KIO::TransferJob::mimeTypeFound, q, [this](KIO::Job *job, const QString &type) {
449 slotMimetype(job, type);
450 });
451 }
452}
453
454void FileCopyJobPrivate::slotData(KIO::Job *, const QByteArray &data)
455{
456 // qDebug() << "data size:" << data.size();
457 Q_ASSERT(m_putJob);
458 if (!m_putJob) {
459 return; // Don't crash
460 }
461 m_getJob->d_func()->internalSuspend();
462 m_putJob->d_func()->internalResume(); // Drink the beer
463 m_buffer += data;
464
465 // On the first set of data incoming, we tell the "put" worker about our
466 // decision about resuming
467 if (!m_resumeAnswerSent) {
468 m_resumeAnswerSent = true;
469 // qDebug() << "(first time) -> send resume answer " << m_canResume;
470 jobWorker(m_putJob)->sendResumeAnswer(m_canResume);
471 }
472}
473
474void FileCopyJobPrivate::slotDataReq(KIO::Job *, QByteArray &data)
475{
476 Q_Q(FileCopyJob);
477 // qDebug();
478 if (!m_resumeAnswerSent && !m_getJob) {
479 // This can't happen
480 q->setError(ERR_INTERNAL);
481 q->setErrorText(QStringLiteral("'Put' job did not send canResume or 'Get' job did not send data!"));
482 m_putJob->kill(FileCopyJob::Quietly);
483 q->removeSubjob(m_putJob);
484 m_putJob = nullptr;
485 q->emitResult();
486 return;
487 }
488 if (m_getJob) {
489 m_getJob->d_func()->internalResume(); // Order more beer
490 m_putJob->d_func()->internalSuspend();
491 }
492 data = m_buffer;
493 m_buffer = QByteArray();
494}
495
496void FileCopyJobPrivate::slotMimetype(KIO::Job *, const QString &type)
497{
498 Q_Q(FileCopyJob);
499 Q_EMIT q->mimeTypeFound(q, type);
500}
501
503{
505 // qDebug() << "this=" << this << "job=" << job;
506 removeSubjob(job);
507
508 // If result comes from copyjob then we are not writing anymore.
509 if (job == d->m_copyJob) {
510 d->m_bFileCopyInProgress = false;
511 }
512
513 // Did job have an error ?
514 if (job->error()) {
515 if ((job == d->m_moveJob) && (job->error() == ERR_UNSUPPORTED_ACTION)) {
516 d->m_moveJob = nullptr;
517 d->startBestCopyMethod();
518 return;
519 } else if ((job == d->m_copyJob) && (job->error() == ERR_UNSUPPORTED_ACTION)) {
520 d->m_copyJob = nullptr;
521 d->startDataPump();
522 return;
523 } else if (job == d->m_getJob) {
524 d->m_getJob = nullptr;
525 if (d->m_putJob) {
526 d->m_putJob->kill(Quietly);
527 removeSubjob(d->m_putJob);
528 }
529 } else if (job == d->m_putJob) {
530 d->m_putJob = nullptr;
531 if (d->m_getJob) {
532 d->m_getJob->kill(Quietly);
533 removeSubjob(d->m_getJob);
534 }
535 } else if (job == d->m_chmodJob) {
536 d->m_chmodJob = nullptr;
537 if (d->m_delJob) {
538 d->m_delJob->kill(Quietly);
539 removeSubjob(d->m_delJob);
540 }
541 } else if (job == d->m_delJob) {
542 d->m_delJob = nullptr;
543 if (d->m_chmodJob) {
544 d->m_chmodJob->kill(Quietly);
545 removeSubjob(d->m_chmodJob);
546 }
547 }
548 setError(job->error());
549 setErrorText(job->errorText());
550 emitResult();
551 return;
552 }
553
554 if (d->m_mustChmod) {
555 // If d->m_permissions == -1, keep the default permissions
556 if (d->m_permissions != -1) {
557 d->m_chmodJob = chmod(d->m_dest, d->m_permissions);
558 addSubjob(d->m_chmodJob);
559 }
560 d->m_mustChmod = false;
561 }
562
563 if (job == d->m_moveJob) {
564 d->m_moveJob = nullptr; // Finished
565 }
566
567 if (job == d->m_copyJob) {
568 d->m_copyJob = nullptr;
569 if (d->m_move) {
570 d->m_delJob = file_delete(d->m_src, HideProgressInfo /*no GUI*/); // Delete source
571 addSubjob(d->m_delJob);
572 }
573 }
574
575 if (job == d->m_getJob) {
576 // qDebug() << "m_getJob finished";
577 d->m_getJob = nullptr; // No action required
578 if (d->m_putJob) {
579 d->m_putJob->d_func()->internalResume();
580 }
581 }
582
583 if (job == d->m_putJob) {
584 // qDebug() << "m_putJob finished";
585 d->m_putJob = nullptr;
586 if (d->m_getJob) {
587 // The get job is still running, probably after emitting data(QByteArray())
588 // and before we receive its finished().
589 d->m_getJob->d_func()->internalResume();
590 }
591 if (d->m_move) {
592 d->m_delJob = file_delete(d->m_src, HideProgressInfo /*no GUI*/); // Delete source
593 addSubjob(d->m_delJob);
594 }
595 }
596
597 if (job == d->m_delJob) {
598 d->m_delJob = nullptr; // Finished
599 }
600
601 if (job == d->m_chmodJob) {
602 d->m_chmodJob = nullptr; // Finished
603 }
604
605 if (!hasSubjobs()) {
606 emitResult();
607 }
608}
609
610bool FileCopyJob::doKill()
611{
612#ifdef Q_OS_WIN
613 // TODO Use SetConsoleCtrlHandler on Windows or similar behaviour.
614 // https://stackoverflow.com/questions/2007516/is-there-a-posix-sigterm-alternative-on-windows-a-gentle-kill-for-console-ap
615 // https://danielkaes.wordpress.com/2009/06/04/how-to-catch-kill-events-with-python/
616 // https://phabricator.kde.org/D25117#566107
617
619
620 // If we are interrupted in the middle of file copying,
621 // we may end up with corrupted file at the destination.
622 // It is better to clean up this file. If a copy is being
623 // made as part of move operation then delete the dest only if
624 // source file is intact (m_delJob == NULL).
625 if (d->m_bFileCopyInProgress && d->m_copyJob && d->m_dest.isLocalFile()) {
626 if (d->m_flags & Overwrite) {
627 QFile::remove(d->m_dest.toLocalFile() + QStringLiteral(".part"));
628 } else {
629 QFile::remove(d->m_dest.toLocalFile());
630 }
631 }
632#endif
633 return Job::doKill();
634}
635
636FileCopyJob *KIO::file_copy(const QUrl &src, const QUrl &dest, int permissions, JobFlags flags)
637{
638 return FileCopyJobPrivate::newJob(src, dest, permissions, false, flags);
639}
640
641FileCopyJob *KIO::file_move(const QUrl &src, const QUrl &dest, int permissions, JobFlags flags)
642{
643 FileCopyJob *job = FileCopyJobPrivate::newJob(src, dest, permissions, true, flags);
644 if (job->uiDelegateExtension()) {
645 job->uiDelegateExtension()->createClipboardUpdater(job, JobUiDelegateExtension::UpdateContent);
646 }
647 return job;
648}
649
650#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.
Definition filecopyjob.h:26
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.
Definition job_base.h:45
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).
Definition simplejob.h:27
The transfer job pumps data into and/or out of a KIO worker.
Definition transferjob.h:26
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:2626
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
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 Tue Mar 26 2024 11:18:51 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.