KIO

filecopyjob.cpp
1 /*
2  This file is part of the KDE libraries
3  SPDX-FileCopyrightText: 2000 Stephan Kulow <[email protected]>
4  SPDX-FileCopyrightText: 2000-2009 David Faure <[email protected]>
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 "slave.h"
15 #include <kio/jobuidelegatefactory.h>
16 
17 #include <KLocalizedString>
18 
19 #include <QFile>
20 #include <QTimer>
21 
22 using namespace KIO;
23 
24 static inline Slave *jobSlave(SimpleJob *job)
25 {
26  return SimpleJobPrivate::get(job)->m_slave;
27 }
28 
29 /** @internal */
30 class KIO::FileCopyJobPrivate : public KIO::JobPrivate
31 {
32 public:
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 
107 static bool isSrcDestSameSlaveProcess(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  */
125 FileCopyJob::FileCopyJob(FileCopyJobPrivate &dd)
126  : Job(dd)
127 {
128  Q_D(FileCopyJob);
129  QTimer::singleShot(0, this, [d]() {
130  d->slotStart();
131  });
132 }
133 
134 void 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 (isSrcDestSameSlaveProcess(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 
160 void FileCopyJobPrivate::startBestCopyMethod()
161 {
162  if (isSrcDestSameSlaveProcess(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 
173 FileCopyJob::~FileCopyJob()
174 {
175 }
176 
178 {
179  Q_D(FileCopyJob);
180  d->m_sourceSize = size;
181  if (size != (KIO::filesize_t)-1) {
183  }
184 }
185 
187 {
188  Q_D(FileCopyJob);
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 
202 void FileCopyJobPrivate::startCopyJob()
203 {
204  startCopyJob(m_src);
205 }
206 
207 void 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 
225 void 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 
239 void 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 
267 bool FileCopyJob::doSuspend()
268 {
269  Q_D(FileCopyJob);
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 
286  Job::doSuspend();
287  return true;
288 }
289 
290 bool FileCopyJob::doResume()
291 {
292  Q_D(FileCopyJob);
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 
309  Job::doResume();
310  return true;
311 }
312 
313 void 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 
339 void 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  jobSlave(m_getJob)->setOffset(jobSlave(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) {
360  auto renameSignal = &AskUserActionInterface::askUserRenameResult;
361 
362  q->connect(askUserActionInterface, renameSignal, q, [=](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 
393 void 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  jobSlave(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  jobSlave(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 
454 void 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  jobSlave(m_putJob)->sendResumeAnswer(m_canResume);
471  }
472 }
473 
474 void 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 
496 void FileCopyJobPrivate::slotMimetype(KIO::Job *, const QString &type)
497 {
498  Q_Q(FileCopyJob);
499 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 78)
500  Q_EMIT q->mimetype(q, type);
501 #endif
502  Q_EMIT q->mimeTypeFound(q, type);
503 }
504 
506 {
507  Q_D(FileCopyJob);
508  // qDebug() << "this=" << this << "job=" << job;
509  removeSubjob(job);
510 
511  // If result comes from copyjob then we are not writing anymore.
512  if (job == d->m_copyJob) {
513  d->m_bFileCopyInProgress = false;
514  }
515 
516  // Did job have an error ?
517  if (job->error()) {
518  if ((job == d->m_moveJob) && (job->error() == ERR_UNSUPPORTED_ACTION)) {
519  d->m_moveJob = nullptr;
520  d->startBestCopyMethod();
521  return;
522  } else if ((job == d->m_copyJob) && (job->error() == ERR_UNSUPPORTED_ACTION)) {
523  d->m_copyJob = nullptr;
524  d->startDataPump();
525  return;
526  } else if (job == d->m_getJob) {
527  d->m_getJob = nullptr;
528  if (d->m_putJob) {
529  d->m_putJob->kill(Quietly);
530  removeSubjob(d->m_putJob);
531  }
532  } else if (job == d->m_putJob) {
533  d->m_putJob = nullptr;
534  if (d->m_getJob) {
535  d->m_getJob->kill(Quietly);
536  removeSubjob(d->m_getJob);
537  }
538  } else if (job == d->m_chmodJob) {
539  d->m_chmodJob = nullptr;
540  if (d->m_delJob) {
541  d->m_delJob->kill(Quietly);
542  removeSubjob(d->m_delJob);
543  }
544  } else if (job == d->m_delJob) {
545  d->m_delJob = nullptr;
546  if (d->m_chmodJob) {
547  d->m_chmodJob->kill(Quietly);
548  removeSubjob(d->m_chmodJob);
549  }
550  }
551  setError(job->error());
552  setErrorText(job->errorText());
553  emitResult();
554  return;
555  }
556 
557  if (d->m_mustChmod) {
558  // If d->m_permissions == -1, keep the default permissions
559  if (d->m_permissions != -1) {
560  d->m_chmodJob = chmod(d->m_dest, d->m_permissions);
561  addSubjob(d->m_chmodJob);
562  }
563  d->m_mustChmod = false;
564  }
565 
566  if (job == d->m_moveJob) {
567  d->m_moveJob = nullptr; // Finished
568  }
569 
570  if (job == d->m_copyJob) {
571  d->m_copyJob = nullptr;
572  if (d->m_move) {
573  d->m_delJob = file_delete(d->m_src, HideProgressInfo /*no GUI*/); // Delete source
574  addSubjob(d->m_delJob);
575  }
576  }
577 
578  if (job == d->m_getJob) {
579  // qDebug() << "m_getJob finished";
580  d->m_getJob = nullptr; // No action required
581  if (d->m_putJob) {
582  d->m_putJob->d_func()->internalResume();
583  }
584  }
585 
586  if (job == d->m_putJob) {
587  // qDebug() << "m_putJob finished";
588  d->m_putJob = nullptr;
589  if (d->m_getJob) {
590  // The get job is still running, probably after emitting data(QByteArray())
591  // and before we receive its finished().
592  d->m_getJob->d_func()->internalResume();
593  }
594  if (d->m_move) {
595  d->m_delJob = file_delete(d->m_src, HideProgressInfo /*no GUI*/); // Delete source
596  addSubjob(d->m_delJob);
597  }
598  }
599 
600  if (job == d->m_delJob) {
601  d->m_delJob = nullptr; // Finished
602  }
603 
604  if (job == d->m_chmodJob) {
605  d->m_chmodJob = nullptr; // Finished
606  }
607 
608  if (!hasSubjobs()) {
609  emitResult();
610  }
611 }
612 
613 bool FileCopyJob::doKill()
614 {
615 #ifdef Q_OS_WIN
616  // TODO Use SetConsoleCtrlHandler on Windows or similar behaviour.
617  // https://stackoverflow.com/questions/2007516/is-there-a-posix-sigterm-alternative-on-windows-a-gentle-kill-for-console-ap
618  // https://danielkaes.wordpress.com/2009/06/04/how-to-catch-kill-events-with-python/
619  // https://phabricator.kde.org/D25117#566107
620 
621  Q_D(FileCopyJob);
622 
623  // If we are interrupted in the middle of file copying,
624  // we may end up with corrupted file at the destination.
625  // It is better to clean up this file. If a copy is being
626  // made as part of move operation then delete the dest only if
627  // source file is intact (m_delJob == NULL).
628  if (d->m_bFileCopyInProgress && d->m_copyJob && d->m_dest.isLocalFile()) {
629  if (d->m_flags & Overwrite) {
630  QFile::remove(d->m_dest.toLocalFile() + QStringLiteral(".part"));
631  } else {
632  QFile::remove(d->m_dest.toLocalFile());
633  }
634  }
635 #endif
636  return Job::doKill();
637 }
638 
639 FileCopyJob *KIO::file_copy(const QUrl &src, const QUrl &dest, int permissions, JobFlags flags)
640 {
641  return FileCopyJobPrivate::newJob(src, dest, permissions, false, flags);
642 }
643 
644 FileCopyJob *KIO::file_move(const QUrl &src, const QUrl &dest, int permissions, JobFlags flags)
645 {
646  FileCopyJob *job = FileCopyJobPrivate::newJob(src, dest, permissions, true, flags);
647  if (job->uiDelegateExtension()) {
648  job->uiDelegateExtension()->createClipboardUpdater(job, JobUiDelegateExtension::UpdateContent);
649  }
650  return job;
651 }
652 
653 #include "moc_filecopyjob.cpp"
@ Overwrite
When set, automatically overwrite the destination if it exists already.
Definition: job_base.h:291
void setSourceSize(KIO::filesize_t size)
If you know the size of the source file, call this method to inform this job.
virtual ClipboardUpdater * createClipboardUpdater(Job *job, ClipboardUpdaterMode mode)
Creates a clipboard updater as a child of the given job.
virtual void registerJob(KJob *job)
static bool canCopyToFile(const QUrl &url)
Returns whether the protocol can copy files/objects directly to the filesystem itself.
static bool canRenameFromFile(const QUrl &url)
Returns whether the protocol can rename (i.e.
KIOCORE_EXPORT SimpleJob * file_delete(const QUrl &src, JobFlags flags=DefaultFlags)
Delete a single file.
Definition: job.cpp:380
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
void setErrorText(const QString &errorText)
bool suspend()
KIOCORE_EXPORT TransferJob * put(const QUrl &url, int permissions, JobFlags flags=DefaultFlags)
Put (means: write)
bool remove()
void percentChanged(KJob *job, unsigned long percent)
QString scheme() const const
qulonglong filesize_t
64-bit file size
Definition: global.h:39
QUrl destUrl() const
Returns the destination URL.
@ NoPrivilegeExecution
When set, notifies the worker that application/job does not want privilege execution.
Definition: job_base.h:300
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:228
@ RenameDialog_NoRename
Don't offer a "Rename" button.
QString userName(QUrl::ComponentFormattingOptions options) const const
KIOCORE_EXPORT TransferJob * get(const QUrl &url, LoadType reload=NoReload, JobFlags flags=DefaultFlags)
Get (means: read).
bool kill(KillVerbosity verbosity=Quietly)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
KIOCORE_EXPORT FileCopyJob * file_copy(const QUrl &src, const QUrl &dest, int permissions=-1, JobFlags flags=DefaultFlags)
Copy a single file.
void setParentJob(Job *parentJob)
Set the parent Job.
Definition: job.cpp:199
KIOCORE_EXPORT KJobTrackerInterface * getJobTracker()
Returns the job tracker to be used by all KIO jobs (in which HideProgressInfo is not set)
Definition: jobtracker.cpp:14
static bool autoResume()
Returns true if partial downloads should be automatically resumed.
QString toString(QUrl::FormattingOptions options) const const
void setTotalAmount(Unit unit, qulonglong amount)
QString i18n(const char *text, const TYPE &arg...)
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
void canResume(KIO::Job *job, KIO::filesize_t offset)
QString errorText() const
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:2649
bool doResume() override
Resume this job.
Definition: job.cpp:186
@ RenameDialog_Overwrite
We have an existing destination, show details about it and offer to overwrite it.
KIOCORE_EXPORT KJobUiDelegate * createDefaultJobUiDelegate()
Convenience method: use default factory, if there's one, to create a delegate and return it.
bool addSubjob(KJob *job) override
Add a job that has to be finished before a result is emitted.
Definition: job.cpp:63
static bool isWorkerOnHoldFor(const QUrl &url)
Returns true if there is a worker on hold for url.
Definition: scheduler.cpp:842
bool doKill() override
Abort this job.
Definition: job.cpp:164
Job * parentJob() const
Returns the parent job, if there is one.
Definition: job.cpp:207
KIOCORE_EXPORT FileCopyJob * file_move(const QUrl &src, const QUrl &dest, int permissions=-1, JobFlags flags=DefaultFlags)
Move a single file.
static bool canRenameToFile(const QUrl &url)
Returns whether the protocol can rename (i.e.
QFlags< RenameDialog_Option > RenameDialog_Options
Stores a combination of RenameDialog_Option values.
bool setProperty(const char *name, const QVariant &value)
void slotResult(KJob *job) override
Called whenever a subjob finishes.
QString host(QUrl::ComponentFormattingOptions options) const 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,...
void totalSize(KJob *job, qulonglong size)
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...
static bool canCopyFromFile(const QUrl &url)
Returns whether the protocol can copy files/objects directly from the filesystem itself.
void mimeTypeFound(KIO::Job *job, const QString &mimeType)
MIME type determined.
int port(int defaultPort) const const
bool isLocalFile() const const
void setUiDelegate(KJobUiDelegate *delegate)
A namespace for KIO globals.
bool isValid() const const
QString password(QUrl::ComponentFormattingOptions options) const const
bool doSuspend() override
Suspend this job.
Definition: job.cpp:175
@ HideProgressInfo
Hide progress information dialog, i.e. don't show a GUI.
Definition: job_base.h:275
KIOCORE_EXPORT QString number(KIO::filesize_t size)
Converts a size to a string representation Not unlike QString::number(...)
Definition: global.cpp:55
void processedSize(KJob *job, qulonglong size)
JobUiDelegateExtension * uiDelegateExtension() const
Retrieves the UI delegate extension used by this job.
Definition: job.cpp:51
void emitResult()
RenameDialog_Result
The result of a rename or skip dialog.
int error() const
QString toString(Qt::DateFormat format) const const
bool hasSubjobs() const
void data(KIO::Job *job, const QByteArray &data)
Data from the worker has arrived.
void dataReq(KIO::Job *job, QByteArray &data)
Request for data.
bool removeSubjob(KJob *job) override
Mark a sub job as being done.
Definition: job.cpp:87
void setError(int errorCode)
void setModificationTime(const QDateTime &mtime)
Sets the modification time of the file.
@ RenameDialog_Resume
Offer a "Resume" button (plus "Resume All" if RenameDialog_MultipleItems).
QUrl srcUrl() const
Returns the source URL.
Q_D(Todo)
virtual QVariant get(ScriptableExtension *callerPrincipal, quint64 objId, const QString &propName)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sat Dec 9 2023 03:51:05 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.