KIO

job.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-2009 Waldo Bastian <[email protected]>
6 
7  SPDX-License-Identifier: LGPL-2.0-or-later
8 */
9 
10 #include "job.h"
11 #include "job_p.h"
12 
13 #include <time.h>
14 
15 #include <KLocalizedString>
16 #include <KStringHandler>
17 
18 #include "scheduler.h"
19 #include "slave.h"
20 #include <kio/jobuidelegateextension.h>
21 
22 using namespace KIO;
23 
24 Job::Job()
25  : KCompositeJob(nullptr)
26  , d_ptr(new JobPrivate)
27 {
28  d_ptr->q_ptr = this;
29  setCapabilities(KJob::Killable | KJob::Suspendable);
30 }
31 
32 Job::Job(JobPrivate &dd)
33  : KCompositeJob(nullptr)
34  , d_ptr(&dd)
35 {
36  d_ptr->q_ptr = this;
37  setCapabilities(KJob::Killable | KJob::Suspendable);
38 }
39 
40 Job::~Job()
41 {
42  delete d_ptr;
43 }
44 
45 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 0)
47 {
48  return uiDelegate();
49 }
50 #endif
51 
53 {
54  Q_D(const Job);
55  return d->m_uiDelegateExtension;
56 }
57 
59 {
60  Q_D(Job);
61  d->m_uiDelegateExtension = extension;
62 }
63 
64 bool Job::addSubjob(KJob *jobBase)
65 {
66  // qDebug() << "addSubjob(" << jobBase << ") this=" << this;
67 
68  bool ok = KCompositeJob::addSubjob(jobBase);
69  KIO::Job *job = qobject_cast<KIO::Job *>(jobBase);
70  if (ok && job) {
71  // Copy metadata into subjob (e.g. window-id, user-timestamp etc.)
72  Q_D(Job);
73  job->mergeMetaData(d->m_outgoingMetaData);
74 
75  // Forward information from that subjob.
76  connect(job, &KJob::speed, this, [this](KJob *job, ulong speed) {
77  Q_UNUSED(job);
79  });
80  job->setProperty("widget", property("widget")); // see KJobWidgets
81  job->setProperty("window", property("window")); // see KJobWidgets
82  job->setProperty("userTimestamp", property("userTimestamp")); // see KJobWidgets
83  job->setUiDelegateExtension(d->m_uiDelegateExtension);
84  }
85  return ok;
86 }
87 
88 bool Job::removeSubjob(KJob *jobBase)
89 {
90  // qDebug() << "removeSubjob(" << jobBase << ") this=" << this << "subjobs=" << subjobs().count();
91  return KCompositeJob::removeSubjob(jobBase);
92 }
93 
94 static QString url_description_string(const QUrl &url)
95 {
96  return url.scheme() == QLatin1String("data") ? QStringLiteral("data:[...]") : KStringHandler::csqueeze(url.toDisplayString(QUrl::PreferLocalFile), 100);
97 }
98 
99 KIO::JobPrivate::~JobPrivate()
100 {
101 }
102 
103 void JobPrivate::emitMoving(KIO::Job *job, const QUrl &src, const QUrl &dest)
104 {
105  static const QString s_title = i18nc("@title job", "Moving");
106  static const QString s_source = i18nc("The source of a file operation", "Source");
107  static const QString s_destination = i18nc("The destination of a file operation", "Destination");
108  Q_EMIT job->description(job, s_title, qMakePair(s_source, url_description_string(src)), qMakePair(s_destination, url_description_string(dest)));
109 }
110 
111 void JobPrivate::emitCopying(KIO::Job *job, const QUrl &src, const QUrl &dest)
112 {
113  static const QString s_title = i18nc("@title job", "Copying");
114  static const QString s_source = i18nc("The source of a file operation", "Source");
115  static const QString s_destination = i18nc("The destination of a file operation", "Destination");
116  Q_EMIT job->description(job, s_title, qMakePair(s_source, url_description_string(src)), qMakePair(s_destination, url_description_string(dest)));
117 }
118 
119 void JobPrivate::emitCreatingDir(KIO::Job *job, const QUrl &dir)
120 {
121  static const QString s_title = i18nc("@title job", "Creating directory");
122  static const QString s_directory = i18n("Directory");
123  Q_EMIT job->description(job, s_title, qMakePair(s_directory, url_description_string(dir)));
124 }
125 
126 void JobPrivate::emitDeleting(KIO::Job *job, const QUrl &url)
127 {
128  static const QString s_title = i18nc("@title job", "Deleting");
129  static const QString s_file = i18n("File");
130  Q_EMIT job->description(job, s_title, qMakePair(s_file, url_description_string(url)));
131 }
132 
133 void JobPrivate::emitStating(KIO::Job *job, const QUrl &url)
134 {
135  static const QString s_title = i18nc("@title job", "Examining");
136  static const QString s_file = i18n("File");
137  Q_EMIT job->description(job, s_title, qMakePair(s_file, url_description_string(url)));
138 }
139 
140 void JobPrivate::emitTransferring(KIO::Job *job, const QUrl &url)
141 {
142  static const QString s_title = i18nc("@title job", "Transferring");
143  static const QString s_source = i18nc("The source of a file operation", "Source");
144  Q_EMIT job->description(job, s_title, qMakePair(s_source, url_description_string(url)));
145 }
146 
147 void JobPrivate::emitMounting(KIO::Job *job, const QString &dev, const QString &point)
148 {
149  Q_EMIT job->description(job, i18nc("@title job", "Mounting"), qMakePair(i18n("Device"), dev), qMakePair(i18n("Mountpoint"), point));
150 }
151 
152 void JobPrivate::emitUnmounting(KIO::Job *job, const QString &point)
153 {
154  Q_EMIT job->description(job, i18nc("@title job", "Unmounting"), qMakePair(i18n("Mountpoint"), point));
155 }
156 
158 {
159  // kill all subjobs, without triggering their result slot
160  for (KJob *job : subjobs()) {
161  job->kill(KJob::Quietly);
162  }
163  clearSubjobs();
164 
165  return true;
166 }
167 
169 {
170  for (KJob *job : subjobs()) {
171  if (!job->suspend()) {
172  return false;
173  }
174  }
175 
176  return true;
177 }
178 
180 {
181  for (KJob *job : subjobs()) {
182  if (!job->resume()) {
183  return false;
184  }
185  }
186 
187  return true;
188 }
189 
190 // Job::errorString is implemented in job_error.cpp
191 
193 {
194  Q_D(Job);
195  Q_ASSERT(d->m_parentJob == nullptr);
196  Q_ASSERT(job);
197  d->m_parentJob = job;
198 }
199 
201 {
202  return d_func()->m_parentJob;
203 }
204 
206 {
207  return d_func()->m_incomingMetaData;
208 }
209 
211 {
212  return d_func()->m_incomingMetaData.value(key, QString());
213 }
214 
215 void Job::setMetaData(const KIO::MetaData &_metaData)
216 {
217  Q_D(Job);
218  d->m_outgoingMetaData = _metaData;
219 }
220 
221 void Job::addMetaData(const QString &key, const QString &value)
222 {
223  d_func()->m_outgoingMetaData.insert(key, value);
224 }
225 
227 {
228  Q_D(Job);
229  for (auto it = values.cbegin(); it != values.cend(); ++it) {
230  d->m_outgoingMetaData.insert(it.key(), it.value());
231  }
232 }
233 
235 {
236  Q_D(Job);
237  for (auto it = values.cbegin(); it != values.cend(); ++it) {
238  // there's probably a faster way
239  if (!d->m_outgoingMetaData.contains(it.key())) {
240  d->m_outgoingMetaData.insert(it.key(), it.value());
241  }
242  }
243 }
244 
246 {
247  return d_func()->m_outgoingMetaData;
248 }
249 
250 QByteArray JobPrivate::privilegeOperationData()
251 {
252  PrivilegeOperationStatus status = OperationNotAllowed;
253 
254  if (m_parentJob) {
255  QByteArray jobData = m_parentJob->d_func()->privilegeOperationData();
256  // Copy meta-data from parent job
257  m_incomingMetaData.insert(QStringLiteral("TestData"), m_parentJob->queryMetaData(QStringLiteral("TestData")));
258  return jobData;
259  } else {
260  if (m_privilegeExecutionEnabled) {
261  status = OperationAllowed;
262  switch (m_operationType) {
263  case ChangeAttr:
264  m_caption = i18n("Change Attribute");
265  m_message = i18n(
266  "Root privileges are required to change file attributes. "
267  "Do you want to continue?");
268  break;
269  case Copy:
270  m_caption = i18n("Copy Files");
271  m_message = i18n(
272  "Root privileges are required to complete the copy operation. "
273  "Do you want to continue?");
274  break;
275  case Delete:
276  m_caption = i18n("Delete Files");
277  m_message = i18n(
278  "Root privileges are required to complete the delete operation. "
279  "However, doing so may damage your system. Do you want to continue?");
280  break;
281  case MkDir:
282  m_caption = i18n("Create Folder");
283  m_message = i18n(
284  "Root privileges are required to create this folder. "
285  "Do you want to continue?");
286  break;
287  case Move:
288  m_caption = i18n("Move Items");
289  m_message = i18n(
290  "Root privileges are required to complete the move operation. "
291  "Do you want to continue?");
292  break;
293  case Rename:
294  m_caption = i18n("Rename");
295  m_message = i18n(
296  "Root privileges are required to complete renaming. "
297  "Do you want to continue?");
298  break;
299  case Symlink:
300  m_caption = i18n("Create Symlink");
301  m_message = i18n(
302  "Root privileges are required to create a symlink. "
303  "Do you want to continue?");
304  break;
305  case Transfer:
306  m_caption = i18n("Transfer data");
307  m_message = i18n(
308  "Root privileges are required to complete transferring data. "
309  "Do you want to continue?");
310  Q_FALLTHROUGH();
311  default:
312  break;
313  }
314 
315  if (m_outgoingMetaData.value(QStringLiteral("UnitTesting")) == QLatin1String("true")) {
316  // Set meta-data for the top-level job
317  m_incomingMetaData.insert(QStringLiteral("TestData"), QStringLiteral("PrivilegeOperationAllowed"));
318  }
319  }
320  }
321 
322  QByteArray parentJobData;
323  QDataStream ds(&parentJobData, QIODevice::WriteOnly);
324  ds << status << m_caption << m_message;
325  return parentJobData;
326 }
327 
328 //////////////////////////
329 
330 class KIO::DirectCopyJobPrivate : public KIO::SimpleJobPrivate
331 {
332 public:
333  DirectCopyJobPrivate(const QUrl &url, int command, const QByteArray &packedArgs)
334  : SimpleJobPrivate(url, command, packedArgs)
335  {
336  }
337 
338  /**
339  * @internal
340  * Called by the scheduler when a @p slave gets to
341  * work on this job.
342  * @param slave the slave that starts working on this job
343  */
344  void start(Slave *slave) override;
345 
346  Q_DECLARE_PUBLIC(DirectCopyJob)
347 };
348 
349 DirectCopyJob::DirectCopyJob(const QUrl &url, const QByteArray &packedArgs)
350  : SimpleJob(*new DirectCopyJobPrivate(url, CMD_COPY, packedArgs))
351 {
353 }
354 
355 DirectCopyJob::~DirectCopyJob()
356 {
357 }
358 
359 void DirectCopyJobPrivate::start(Slave *slave)
360 {
361  Q_Q(DirectCopyJob);
362  q->connect(slave, &SlaveInterface::canResume, q, &DirectCopyJob::slotCanResume);
364 }
365 
366 void DirectCopyJob::slotCanResume(KIO::filesize_t offset)
367 {
368  Q_EMIT canResume(this, offset);
369 }
370 
371 //////////////////////////
372 
374 {
375  KIO_ARGS << src << qint8(true); // isFile
376  SimpleJob *job = SimpleJobPrivate::newJob(src, CMD_DEL, packedArgs, flags);
377  if (job->uiDelegateExtension()) {
378  job->uiDelegateExtension()->createClipboardUpdater(job, JobUiDelegateExtension::RemoveContent);
379  }
380  return job;
381 }
382 
383 //////////
384 ////
385 
386 #include "moc_job_base.cpp"
387 #include "moc_job_p.cpp"
bool resume()
virtual ClipboardUpdater * createClipboardUpdater(Job *job, ClipboardUpdaterMode mode)
Creates a clipboard updater as a child of the given job.
KIOCORE_EXPORT SimpleJob * file_delete(const QUrl &src, JobFlags flags=DefaultFlags)
Delete a single file.
Definition: job.cpp:373
void setUiDelegateExtension(JobUiDelegateExtension *extension)
Sets the UI delegate extension to be used by this job.
Definition: job.cpp:58
bool suspend()
void clearSubjobs()
void mergeMetaData(const QMap< QString, QString > &values)
Add key/value pairs to the meta data that is sent to the slave.
Definition: job.cpp:234
void speed(KJob *job, unsigned long speed)
QString scheme() const const
qulonglong filesize_t
64-bit file size
Definition: global.h:39
Q_SCRIPTABLE Q_NOREPLY void start()
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:221
void setMetaData(const KIO::MetaData &metaData)
Set meta data to be sent to the slave, replacing existing meta data.
Definition: job.cpp:215
bool kill(KillVerbosity verbosity=Quietly)
virtual bool removeSubjob(KJob *job)
void emitSpeed(unsigned long speed)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QString queryMetaData(const QString &key)
Query meta data received from the slave.
Definition: job.cpp:210
KJobUiDelegate * uiDelegate() const
void setParentJob(Job *parentJob)
Set the parent Job.
Definition: job.cpp:192
const QList< KJob * > & subjobs() const
QString i18n(const char *text, const TYPE &arg...)
MetaData metaData() const
Get meta data received from the slave.
Definition: job.cpp:205
NETWORKMANAGERQT_EXPORT NetworkManager::Status status()
void description(KJob *job, const QString &title, const QPair< QString, QString > &field1=QPair< QString, QString >(), const QPair< QString, QString > &field2=QPair< QString, QString >())
bool doResume() override
Resume this job.
Definition: job.cpp:179
virtual bool addSubjob(KJob *job)
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:64
bool doKill() override
Abort this job.
Definition: job.cpp:157
Job * parentJob() const
Returns the parent job, if there is one.
Definition: job.cpp:200
KJobUiDelegate * ui() const
Retrieves the UI delegate of this job.
Definition: job.cpp:46
MetaData outgoingMetaData() const
Definition: job.cpp:245
bool setProperty(const char *name, const QVariant &value)
PrivilegeOperationStatus
Specifies privilege file operation status.
Definition: global.h:321
void setUiDelegate(KJobUiDelegate *delegate)
A namespace for KIO globals.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
bool doSuspend() override
Suspend this job.
Definition: job.cpp:168
JobUiDelegateExtension * uiDelegateExtension() const
Retrieves the UI delegate extension used by this job.
Definition: job.cpp:52
bool removeSubjob(KJob *job) override
Mark a sub job as being done.
Definition: job.cpp:88
QVector< V > values(const QMultiHash< K, V > &c)
Q_D(Todo)
QVariant property(const char *name) const const
QByteArray & insert(int i, char ch)
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Mon Jun 27 2022 04:04:25 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.