KIO

deletejob.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  SPDX-FileCopyrightText: 2000 Waldo Bastian <[email protected]>
6 
7  SPDX-License-Identifier: LGPL-2.0-or-later
8 */
9 
10 #include "deletejob.h"
11 
12 #include "../pathhelpers_p.h"
13 #include "job.h" // buildErrorString
14 #include "kcoredirlister.h"
15 #include "kprotocolmanager.h"
16 #include "listjob.h"
17 #include "scheduler.h"
18 #include "statjob.h"
19 #include <KDirWatch>
20 #include <kdirnotify.h>
21 
22 #include <KLocalizedString>
23 #include <kio/jobuidelegatefactory.h>
24 
25 #include <QDir>
26 #include <QFile>
27 #include <QFileInfo>
28 #include <QMetaObject>
29 #include <QPointer>
30 #include <QThread>
31 #include <QTimer>
32 
33 #include "job_p.h"
34 
35 extern bool kio_resolve_local_urls; // from copyjob.cpp, abused here to save a symbol.
36 
37 static bool isHttpProtocol(const QString &protocol)
38 {
39  return (protocol.startsWith(QLatin1String("webdav"), Qt::CaseInsensitive) || protocol.startsWith(QLatin1String("http"), Qt::CaseInsensitive));
40 }
41 
42 namespace KIO
43 {
44 enum DeleteJobState {
45  DELETEJOB_STATE_STATING,
46  DELETEJOB_STATE_DELETING_FILES,
47  DELETEJOB_STATE_DELETING_DIRS,
48 };
49 
50 class DeleteJobIOWorker : public QObject
51 {
52  Q_OBJECT
53 
54 Q_SIGNALS:
55  void rmfileResult(bool succeeded, bool isLink);
56  void rmddirResult(bool succeeded);
57 
58 public Q_SLOTS:
59 
60  /**
61  * Deletes the file @p url points to
62  * The file must be a LocalFile
63  */
64  void rmfile(const QUrl &url, bool isLink)
65  {
66  Q_EMIT rmfileResult(QFile::remove(url.toLocalFile()), isLink);
67  }
68 
69  /**
70  * Deletes the directory @p url points to
71  * The directory must be a LocalFile
72  */
73  void rmdir(const QUrl &url)
74  {
75  Q_EMIT rmddirResult(QDir().rmdir(url.toLocalFile()));
76  }
77 };
78 
79 class DeleteJobPrivate : public KIO::JobPrivate
80 {
81 public:
82  explicit DeleteJobPrivate(const QList<QUrl> &src)
83  : state(DELETEJOB_STATE_STATING)
84  , m_processedFiles(0)
85  , m_processedDirs(0)
86  , m_totalFilesDirs(0)
87  , m_srcList(src)
88  , m_currentStat(m_srcList.begin())
89  , m_reportTimer(nullptr)
90  {
91  }
92  DeleteJobState state;
93  int m_processedFiles;
94  int m_processedDirs;
95  int m_totalFilesDirs;
96  QUrl m_currentURL;
97  QList<QUrl> files;
98  QList<QUrl> symlinks;
100  QList<QUrl> m_srcList;
101  QList<QUrl>::iterator m_currentStat;
102  QSet<QString> m_parentDirs;
103  QTimer *m_reportTimer;
104  DeleteJobIOWorker *m_ioworker = nullptr;
105  QThread *m_thread = nullptr;
106 
107  void statNextSrc();
108  DeleteJobIOWorker *worker();
109  void currentSourceStated(bool isDir, bool isLink);
110  void finishedStatPhase();
111  void deleteNextFile();
112  void deleteNextDir();
113  void restoreDirWatch() const;
114  void slotReport();
115  void slotStart();
116  void slotEntries(KIO::Job *, const KIO::UDSEntryList &list);
117 
118  /// Callback of worker rmfile
119  void rmFileResult(bool result, bool isLink);
120  /// Callback of worker rmdir
121  void rmdirResult(bool result);
122  void deleteFileUsingJob(const QUrl &url, bool isLink);
123  void deleteDirUsingJob(const QUrl &url);
124 
125  ~DeleteJobPrivate() override;
126 
127  Q_DECLARE_PUBLIC(DeleteJob)
128 
129  static inline DeleteJob *newJob(const QList<QUrl> &src, JobFlags flags)
130  {
131  DeleteJob *job = new DeleteJob(*new DeleteJobPrivate(src));
133  if (!(flags & HideProgressInfo)) {
135  }
136  if (!(flags & NoPrivilegeExecution)) {
137  job->d_func()->m_privilegeExecutionEnabled = true;
138  job->d_func()->m_operationType = Delete;
139  }
140  return job;
141  }
142 };
143 
144 } // namespace KIO
145 
146 using namespace KIO;
147 
148 DeleteJob::DeleteJob(DeleteJobPrivate &dd)
149  : Job(dd)
150 {
151  d_func()->m_reportTimer = new QTimer(this);
152  connect(d_func()->m_reportTimer, &QTimer::timeout, this, [this]() {
153  d_func()->slotReport();
154  });
155  // this will update the report dialog with 5 Hz, I think this is fast enough, aleXXX
156  d_func()->m_reportTimer->start(200);
157 
158  QTimer::singleShot(0, this, SLOT(slotStart()));
159 }
160 
161 DeleteJob::~DeleteJob()
162 {
163 }
164 
165 DeleteJobPrivate::~DeleteJobPrivate()
166 {
167  if (m_thread) {
168  m_thread->quit();
169  m_thread->wait();
170  delete m_thread;
171  }
172 }
173 
175 {
176  return d_func()->m_srcList;
177 }
178 
179 void DeleteJobPrivate::slotStart()
180 {
181  statNextSrc();
182 }
183 
184 DeleteJobIOWorker *DeleteJobPrivate::worker()
185 {
186  Q_Q(DeleteJob);
187 
188  if (!m_ioworker) {
189  m_thread = new QThread();
190 
191  m_ioworker = new DeleteJobIOWorker;
192  m_ioworker->moveToThread(m_thread);
193  QObject::connect(m_thread, &QThread::finished, m_ioworker, &QObject::deleteLater);
194  QObject::connect(m_ioworker, &DeleteJobIOWorker::rmfileResult, q, [=](bool result, bool isLink) {
195  this->rmFileResult(result, isLink);
196  });
197  QObject::connect(m_ioworker, &DeleteJobIOWorker::rmddirResult, q, [=](bool result) {
198  this->rmdirResult(result);
199  });
200  m_thread->start();
201  }
202 
203  return m_ioworker;
204 }
205 
206 void DeleteJobPrivate::slotReport()
207 {
208  Q_Q(DeleteJob);
209  Q_EMIT q->deleting(q, m_currentURL);
210 
211  // TODO: maybe we could skip everything else when (flags & HideProgressInfo) ?
212  JobPrivate::emitDeleting(q, m_currentURL);
213 
214  switch (state) {
215  case DELETEJOB_STATE_STATING:
216  q->setTotalAmount(KJob::Files, files.count());
217  q->setTotalAmount(KJob::Directories, dirs.count());
218  break;
219  case DELETEJOB_STATE_DELETING_DIRS:
220  q->setProcessedAmount(KJob::Directories, m_processedDirs);
221  q->emitPercent(m_processedFiles + m_processedDirs, m_totalFilesDirs);
222  break;
223  case DELETEJOB_STATE_DELETING_FILES:
224  q->setProcessedAmount(KJob::Files, m_processedFiles);
225  q->emitPercent(m_processedFiles, m_totalFilesDirs);
226  break;
227  }
228 }
229 
230 void DeleteJobPrivate::slotEntries(KIO::Job *job, const UDSEntryList &list)
231 {
234  for (; it != end; ++it) {
235  const UDSEntry &entry = *it;
237 
238  Q_ASSERT(!displayName.isEmpty());
239  if (displayName != QLatin1String("..") && displayName != QLatin1String(".")) {
240  QUrl url;
241  const QString urlStr = entry.stringValue(KIO::UDSEntry::UDS_URL);
242  if (!urlStr.isEmpty()) {
243  url = QUrl(urlStr);
244  } else {
245  url = static_cast<SimpleJob *>(job)->url(); // assumed to be a dir
246  url.setPath(concatPaths(url.path(), displayName));
247  }
248 
249  // qDebug() << displayName << "(" << url << ")";
250  if (entry.isLink()) {
251  symlinks.append(url);
252  } else if (entry.isDir()) {
253  dirs.append(url);
254  } else {
255  files.append(url);
256  }
257  }
258  }
259 }
260 
261 void DeleteJobPrivate::statNextSrc()
262 {
263  Q_Q(DeleteJob);
264  // qDebug();
265  if (m_currentStat != m_srcList.end()) {
266  m_currentURL = (*m_currentStat);
267 
268  // if the file system doesn't support deleting, we do not even stat
269  if (!KProtocolManager::supportsDeleting(m_currentURL)) {
270  QPointer<DeleteJob> that = q;
271  ++m_currentStat;
272  Q_EMIT q->warning(q, buildErrorString(ERR_CANNOT_DELETE, m_currentURL.toDisplayString()));
273  if (that) {
274  statNextSrc();
275  }
276  return;
277  }
278  // Stat it
279  state = DELETEJOB_STATE_STATING;
280 
281  // Fast path for KFileItems in directory views
282  while (m_currentStat != m_srcList.end()) {
283  m_currentURL = (*m_currentStat);
284  const KFileItem cachedItem = KCoreDirLister::cachedItemForUrl(m_currentURL);
285  if (cachedItem.isNull()) {
286  break;
287  }
288  // qDebug() << "Found cached info about" << m_currentURL << "isDir=" << cachedItem.isDir() << "isLink=" << cachedItem.isLink();
289  currentSourceStated(cachedItem.isDir(), cachedItem.isLink());
290  ++m_currentStat;
291  }
292 
293  // Hook for unit test to disable the fast path.
294  if (!kio_resolve_local_urls) {
295  // Fast path for local files
296  // (using a loop, instead of a huge recursion)
297  while (m_currentStat != m_srcList.end() && (*m_currentStat).isLocalFile()) {
298  m_currentURL = (*m_currentStat);
299  QFileInfo fileInfo(m_currentURL.toLocalFile());
300  currentSourceStated(fileInfo.isDir(), fileInfo.isSymLink());
301  ++m_currentStat;
302  }
303  }
304  if (m_currentStat == m_srcList.end()) {
305  // Done, jump to the last else of this method
306  statNextSrc();
307  } else {
308  KIO::SimpleJob *job = KIO::statDetails(m_currentURL, StatJob::SourceSide, KIO::StatBasic, KIO::HideProgressInfo);
309  // qDebug() << "stat'ing" << m_currentURL;
310  q->addSubjob(job);
311  }
312  } else {
313  if (!q->hasSubjobs()) { // don't go there yet if we're still listing some subdirs
314  finishedStatPhase();
315  }
316  }
317 }
318 
319 void DeleteJobPrivate::finishedStatPhase()
320 {
321  m_totalFilesDirs = files.count() + symlinks.count() + dirs.count();
322  slotReport();
323  // Now we know which dirs hold the files we're going to delete.
324  // To speed things up and prevent double-notification, we disable KDirWatch
325  // on those dirs temporarily (using KDirWatch::self, that's the instance
326  // used by e.g. kdirlister).
327  for (const QString &dir : std::as_const(m_parentDirs)) {
329  }
330  state = DELETEJOB_STATE_DELETING_FILES;
331  deleteNextFile();
332 }
333 
334 void DeleteJobPrivate::rmFileResult(bool result, bool isLink)
335 {
336  if (result) {
337  m_processedFiles++;
338 
339  if (isLink) {
340  symlinks.removeFirst();
341  } else {
342  files.removeFirst();
343  }
344 
345  deleteNextFile();
346  } else {
347  // fallback if QFile::remove() failed (we'll use the job's error handling in that case)
348  deleteFileUsingJob(m_currentURL, isLink);
349  }
350 }
351 
352 void DeleteJobPrivate::deleteFileUsingJob(const QUrl &url, bool isLink)
353 {
354  Q_Q(DeleteJob);
355 
356  SimpleJob *job;
357  if (isHttpProtocol(url.scheme())) {
359  } else {
361  job->setParentJob(q);
362  }
363 
364  if (isLink) {
365  symlinks.removeFirst();
366  } else {
367  files.removeFirst();
368  }
369 
370  q->addSubjob(job);
371 }
372 
373 void DeleteJobPrivate::deleteNextFile()
374 {
375  // qDebug();
376 
377  // if there is something else to delete
378  // the loop is run using callbacks slotResult and rmFileResult
379  if (!files.isEmpty() || !symlinks.isEmpty()) {
380  // Take first file to delete out of list
381  QList<QUrl>::iterator it = files.begin();
382  const bool isLink = (it == files.end()); // No more files
383  if (isLink) {
384  it = symlinks.begin(); // Pick up a symlink to delete
385  }
386  m_currentURL = (*it);
387 
388  // If local file, try do it directly
389  if (m_currentURL.isLocalFile()) {
390  // separate thread will do the work
391  QMetaObject::invokeMethod(worker(), "rmfile", Qt::QueuedConnection, Q_ARG(QUrl, m_currentURL), Q_ARG(bool, isLink));
392  } else {
393  // if remote, use a job
394  deleteFileUsingJob(m_currentURL, isLink);
395  }
396  return;
397  }
398 
399  state = DELETEJOB_STATE_DELETING_DIRS;
400  deleteNextDir();
401 }
402 
403 void DeleteJobPrivate::rmdirResult(bool result)
404 {
405  if (result) {
406  m_processedDirs++;
407  dirs.removeLast();
408  deleteNextDir();
409  } else {
410  // fallback
411  deleteDirUsingJob(m_currentURL);
412  }
413 }
414 
415 void DeleteJobPrivate::deleteDirUsingJob(const QUrl &url)
416 {
417  Q_Q(DeleteJob);
418 
419  // Call rmdir - works for kioslaves with canDeleteRecursive too,
420  // CMD_DEL will trigger the recursive deletion in the slave.
421  SimpleJob *job = KIO::rmdir(url);
422  job->setParentJob(q);
423  job->addMetaData(QStringLiteral("recurse"), QStringLiteral("true"));
424  dirs.removeLast();
425  q->addSubjob(job);
426 }
427 
428 void DeleteJobPrivate::deleteNextDir()
429 {
430  Q_Q(DeleteJob);
431 
432  if (!dirs.isEmpty()) { // some dirs to delete ?
433 
434  // the loop is run using callbacks slotResult and rmdirResult
435  // Take first dir to delete out of list - last ones first !
436  QList<QUrl>::iterator it = --dirs.end();
437  m_currentURL = (*it);
438  // If local dir, try to rmdir it directly
439  if (m_currentURL.isLocalFile()) {
440  // delete it on separate worker thread
441  QMetaObject::invokeMethod(worker(), "rmdir", Qt::QueuedConnection, Q_ARG(QUrl, m_currentURL));
442  } else {
443  deleteDirUsingJob(m_currentURL);
444  }
445  return;
446  }
447 
448  // Re-enable watching on the dirs that held the deleted files
449  restoreDirWatch();
450 
451  // Finished - tell the world
452  if (!m_srcList.isEmpty()) {
453  // qDebug() << "KDirNotify'ing FilesRemoved" << m_srcList;
454 #ifndef KIO_ANDROID_STUB
455  org::kde::KDirNotify::emitFilesRemoved(m_srcList);
456 #endif
457  }
458  if (m_reportTimer != nullptr) {
459  m_reportTimer->stop();
460  }
461  // display final numbers
462  q->setProcessedAmount(KJob::Directories, m_processedDirs);
463  q->setProcessedAmount(KJob::Files, m_processedFiles);
464  q->emitPercent(m_processedFiles + m_processedDirs, m_totalFilesDirs);
465 
466  q->emitResult();
467 }
468 
469 void DeleteJobPrivate::restoreDirWatch() const
470 {
471  const auto itEnd = m_parentDirs.constEnd();
472  for (auto it = m_parentDirs.constBegin(); it != itEnd; ++it) {
474  }
475 }
476 
477 void DeleteJobPrivate::currentSourceStated(bool isDir, bool isLink)
478 {
479  Q_Q(DeleteJob);
480  const QUrl url = (*m_currentStat);
481  if (isDir && !isLink) {
482  // Add toplevel dir in list of dirs
483  dirs.append(url);
484  if (url.isLocalFile()) {
485  // We are about to delete this dir, no need to watch it
486  // Maybe we should ask kdirwatch to remove all watches recursively?
487  // But then there would be no feedback (things disappearing progressively) during huge deletions
489  }
491  // qDebug() << url << "is a directory, let's list it";
493 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 69)
494  // TODO KF6: remove legacy details code path
495  newjob->addMetaData(QStringLiteral("details"), QStringLiteral("0"));
496 #endif
497  newjob->addMetaData(QStringLiteral("statDetails"), QString::number(KIO::StatBasic));
498  newjob->setUnrestricted(true); // No KIOSK restrictions
499  QObject::connect(newjob, &KIO::ListJob::entries, q, [this](KIO::Job *job, const KIO::UDSEntryList &list) {
500  slotEntries(job, list);
501  });
502  q->addSubjob(newjob);
503  // Note that this listing job will happen in parallel with other stat jobs.
504  }
505  } else {
506  if (isLink) {
507  // qDebug() << "Target is a symlink";
508  symlinks.append(url);
509  } else {
510  // qDebug() << "Target is a file";
511  files.append(url);
512  }
513  }
514  if (url.isLocalFile()) {
516  m_parentDirs.insert(parentDir);
517  }
518 }
519 
520 void DeleteJob::slotResult(KJob *job)
521 {
522  Q_D(DeleteJob);
523  switch (d->state) {
524  case DELETEJOB_STATE_STATING:
525  removeSubjob(job);
526 
527  // Was this a stat job or a list job? We do both in parallel.
528  if (StatJob *statJob = qobject_cast<StatJob *>(job)) {
529  // Was there an error while stating ?
530  if (job->error()) {
531  // Probably : doesn't exist
532  Job::slotResult(job); // will set the error and emit result(this)
533  d->restoreDirWatch();
534  return;
535  }
536 
537  const UDSEntry &entry = statJob->statResult();
538  // Is it a file or a dir ?
539  const bool isLink = entry.isLink();
540  const bool isDir = entry.isDir();
541  d->currentSourceStated(isDir, isLink);
542 
543  ++d->m_currentStat;
544  d->statNextSrc();
545  } else {
546  if (job->error()) {
547  // Try deleting nonetheless, it may be empty (and non-listable)
548  }
549  if (!hasSubjobs()) {
550  d->finishedStatPhase();
551  }
552  }
553  break;
554  case DELETEJOB_STATE_DELETING_FILES:
555  // Propagate the subjob's metadata (a SimpleJob) to the real DeleteJob
556  // FIXME: setMetaData() in the KIO API only allows access to outgoing metadata,
557  // but we need to alter the incoming one
558  d->m_incomingMetaData = dynamic_cast<KIO::Job *>(job)->metaData();
559 
560  if (job->error()) {
561  Job::slotResult(job); // will set the error and emit result(this)
562  d->restoreDirWatch();
563  return;
564  }
565  removeSubjob(job);
566  Q_ASSERT(!hasSubjobs());
567  d->m_processedFiles++;
568 
569  d->deleteNextFile();
570  break;
571  case DELETEJOB_STATE_DELETING_DIRS:
572  if (job->error()) {
573  Job::slotResult(job); // will set the error and emit result(this)
574  d->restoreDirWatch();
575  return;
576  }
577  removeSubjob(job);
578  Q_ASSERT(!hasSubjobs());
579  d->m_processedDirs++;
580  // emit processedAmount( this, KJob::Directories, d->m_processedDirs );
581  // emitPercent( d->m_processedFiles + d->m_processedDirs, d->m_totalFilesDirs );
582 
583  d->deleteNextDir();
584  break;
585  default:
586  Q_ASSERT(0);
587  }
588 }
589 
590 DeleteJob *KIO::del(const QUrl &src, JobFlags flags)
591 {
592  QList<QUrl> srcList;
593  srcList.append(src);
594  DeleteJob *job = DeleteJobPrivate::newJob(srcList, flags);
595  if (job->uiDelegateExtension()) {
596  job->uiDelegateExtension()->createClipboardUpdater(job, JobUiDelegateExtension::RemoveContent);
597  }
598  return job;
599 }
600 
602 {
603  DeleteJob *job = DeleteJobPrivate::newJob(src, flags);
604  if (job->uiDelegateExtension()) {
605  job->uiDelegateExtension()->createClipboardUpdater(job, JobUiDelegateExtension::RemoveContent);
606  }
607  return job;
608 }
609 
610 #include "deletejob.moc"
611 #include "moc_deletejob.cpp"
static KFileItem cachedItemForUrl(const QUrl &url)
Return the KFileItem for the given URL, if it was listed recently and it's still in the cache,...
Q_OBJECTQ_OBJECT
void append(const T &value)
bool stopDirScan(const QString &path)
virtual ClipboardUpdater * createClipboardUpdater(Job *job, ClipboardUpdaterMode mode)
Creates a clipboard updater as a child of the given job.
KIOCORE_EXPORT TransferJob * http_delete(const QUrl &url, JobFlags flags=DefaultFlags)
HTTP DELETE.
virtual void registerJob(KJob *job)
KIOCORE_EXPORT SimpleJob * file_delete(const QUrl &src, JobFlags flags=DefaultFlags)
Delete a single file.
Definition: job.cpp:381
QString number(int n, int base)
CaseInsensitive
Q_SLOTSQ_SLOTS
bool remove()
Q_EMITQ_EMIT
QString scheme() const const
int count(const T &value) const const
@ NoPrivilegeExecution
When set, notifies the slave that application/job does not want privilege execution.
Definition: job_base.h:299
bool isDir() const
Definition: udsentry.cpp:384
void addMetaData(const QString &key, const QString &value)
Add key/value pair to the meta data that is sent to the slave.
Definition: job.cpp:229
static bool canDeleteRecursive(const QUrl &url)
Returns whether the protocol can recursively delete directories by itself.
bool wait(QDeadlineTimer deadline)
void finished()
void entries(KIO::Job *job, const KIO::UDSEntryList &list)
This signal emits the entry found by the job while listing.
bool restartDirScan(const QString &path)
KIOFILEWIDGETS_EXPORT QStringList list(const QString &fileClass)
Returns a list of directories associated with this file-class.
Definition: krecentdirs.cpp:39
const QList< QKeySequence > & begin()
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
@ UDS_NAME
Filename - as displayed in directory listings etc.
Definition: udsentry.h:249
void setParentJob(Job *parentJob)
Set the parent Job.
Definition: job.cpp:200
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
void quit()
QString stringValue(uint field) const
Definition: udsentry.cpp:374
void deleteLater()
KIOCORE_EXPORT ListJob * listRecursive(const QUrl &url, JobFlags flags=DefaultFlags, bool includeHidden=true)
The same as the previous method, but recurses subdirectories.
Definition: listjob.cpp:249
KIOCORE_EXPORT QString buildErrorString(int errorCode, const QString &errorText)
Returns a translated error message for errorCode using the additional error information provided by e...
Definition: job_error.cpp:27
KIOCORE_EXPORT DeleteJob * del(const QUrl &src, JobFlags flags=DefaultFlags)
Delete a file or directory.
Definition: deletejob.cpp:590
MetaData metaData() const
Get meta data received from the slave.
Definition: job.cpp:213
bool isNull() const
Return true if default-constructed.
Definition: kfileitem.cpp:1700
@ UDS_URL
An alternative URL (If different from the caption).
Definition: udsentry.h:276
StripTrailingSlash
QSet::const_iterator constBegin() const const
void start(QThread::Priority priority)
void timeout()
bool isEmpty() const const
void removeFirst()
QString toDisplayString(QUrl::FormattingOptions options) const const
QSet::const_iterator constEnd() const const
KIOCORE_EXPORT KJobUiDelegate * createDefaultJobUiDelegate()
Convenience method: use default factory, if there's one, to create a delegate and return it.
QueuedConnection
bool isEmpty() const const
QString toLocalFile() const const
@ StatBasic
Filename, access, type, size, linkdest.
Definition: global.h:362
void setUnrestricted(bool unrestricted)
Do not apply any KIOSK restrictions to this job.
Definition: listjob.cpp:254
static KDirWatch * self()
AKONADI_CALENDAR_EXPORT QString displayName(Akonadi::ETMCalendar *calendar, const Akonadi::Collection &collection)
Q_SIGNALSQ_SIGNALS
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
bool isLink() const
Definition: udsentry.cpp:389
static bool supportsDeleting(const QUrl &url)
Returns whether the protocol can delete files/objects.
QString path(QUrl::ComponentFormattingOptions options) const const
QList< QUrl > urls() const
Returns the list of URLs.
Definition: deletejob.cpp:174
void stop()
void setPath(const QString &path, QUrl::ParsingMode mode)
KStandardDirs * dirs()
bool isLocalFile() const const
bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericReturnArgument ret, QGenericArgument val0, QGenericArgument val1, QGenericArgument val2, QGenericArgument val3, QGenericArgument val4, QGenericArgument val5, QGenericArgument val6, QGenericArgument val7, QGenericArgument val8, QGenericArgument val9)
void setUiDelegate(KJobUiDelegate *delegate)
QUrl adjusted(QUrl::FormattingOptions options) const const
KIOCORE_EXPORT StatJob * statDetails(const QUrl &url, KIO::StatJob::StatSide side, KIO::StatDetails details=KIO::StatDefaultDetails, JobFlags flags=DefaultFlags)
Find all details for one file or directory.
Definition: statjob.cpp:263
A namespace for KIO globals.
virtual void slotResult(KJob *job)
KIOCORE_EXPORT SimpleJob * rmdir(const QUrl &url)
Removes a single directory.
Definition: simplejob.cpp:349
QSet::iterator insert(const T &value)
QList::iterator begin()
@ HideProgressInfo
Hide progress information dialog, i.e. don't show a GUI.
Definition: job_base.h:274
JobUiDelegateExtension * uiDelegateExtension() const
Retrieves the UI delegate extension used by this job.
Definition: job.cpp:52
int error() const
bool hasSubjobs() const
QList::iterator end()
bool removeSubjob(KJob *job) override
Mark a sub job as being done.
Definition: job.cpp:88
const QList< QKeySequence > & end()
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Tue Aug 9 2022 03:53:37 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.