KParts

readonlypart.cpp
1 /*
2  This file is part of the KDE project
3  SPDX-FileCopyrightText: 1999 Simon Hausmann <[email protected]>
4  SPDX-FileCopyrightText: 1999-2005 David Faure <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #include "readonlypart.h"
10 #include "readonlypart_p.h"
11 
12 #include "kparts_logging.h"
13 
14 #include "browserextension.h"
15 #include "guiactivateevent.h"
16 
17 #include <KIO/FileCopyJob>
18 #include <KIO/StatJob>
19 #include <KJobWidgets>
20 #include <KProtocolInfo>
21 
22 #include <QDir>
23 #include <QFileInfo>
24 #include <QMimeDatabase>
25 #include <QTemporaryFile>
26 
27 using namespace KParts;
28 
30  : Part(*new ReadOnlyPartPrivate(this), parent)
31 {
32 }
33 
34 ReadOnlyPart::ReadOnlyPart(ReadOnlyPartPrivate &dd, QObject *parent)
35  : Part(dd, parent)
36 {
37 }
38 
40 {
42 }
43 
44 QUrl ReadOnlyPart::url() const
45 {
46  Q_D(const ReadOnlyPart);
47 
48  return d->m_url;
49 }
50 
51 void ReadOnlyPart::setUrl(const QUrl &url)
52 {
54 
55  if (d->m_url != url) {
56  d->m_url = url;
57  Q_EMIT urlChanged(url);
58  }
59 }
60 
62 {
63  Q_D(const ReadOnlyPart);
64 
65  return d->m_file;
66 }
67 
68 void ReadOnlyPart::setLocalFilePath(const QString &localFilePath)
69 {
71 
72  d->m_file = localFilePath;
73 }
74 
75 #if KPARTS_BUILD_DEPRECATED_SINCE(5, 0)
77 {
78  Q_D(const ReadOnlyPart);
79 
80  return d->m_bTemp;
81 }
82 #endif
83 
84 #if KPARTS_BUILD_DEPRECATED_SINCE(5, 0)
86 {
88 
89  d->m_bTemp = temp;
90 }
91 #endif
92 
94 {
96 
97  d->m_showProgressInfo = show;
98 }
99 
101 {
102  Q_D(const ReadOnlyPart);
103 
104  return d->m_showProgressInfo;
105 }
106 
107 #if KPARTS_BUILD_DEPRECATED_SINCE(3, 0)
109 {
110  Q_D(ReadOnlyPart);
111 
112  d->m_showProgressInfo = show;
113 }
114 #endif
115 
116 bool ReadOnlyPart::openUrl(const QUrl &url)
117 {
118  Q_D(ReadOnlyPart);
119 
120  if (!url.isValid()) {
121  return false;
122  }
123  if (d->m_bAutoDetectedMime) {
124  d->m_arguments.setMimeType(QString());
125  d->m_bAutoDetectedMime = false;
126  }
127  OpenUrlArguments args = d->m_arguments;
128  d->m_closeUrlFromOpenUrl = true;
129  const bool closed = closeUrl();
130  d->m_closeUrlFromOpenUrl = false;
131  if (!closed) {
132  return false;
133  }
134  d->m_arguments = args;
135  setUrl(url);
136 
137  d->m_file.clear();
138 
139  if (d->m_url.isLocalFile()) {
140  d->m_file = d->m_url.toLocalFile();
141  return d->openLocalFile();
142  } else if (KProtocolInfo::protocolClass(url.scheme()) == QLatin1String(":local")) {
143  // Maybe we can use a "local path", to avoid a temp copy?
144  KIO::JobFlags flags = d->m_showProgressInfo ? KIO::DefaultFlags : KIO::HideProgressInfo;
145  d->m_statJob = KIO::mostLocalUrl(d->m_url, flags);
146  KJobWidgets::setWindow(d->m_statJob, widget());
147  connect(d->m_statJob, &KJob::result, this, [d](KJob *job) {
148  d->slotStatJobFinished(job);
149  });
150  return true;
151  } else {
152  d->openRemoteFile();
153  return true;
154  }
155 }
156 
158 {
159  qCWarning(KPARTSLOG) << "Default implementation of ReadOnlyPart::openFile called!" << metaObject()->className()
160  << "should reimplement either openUrl or openFile.";
161  return false;
162 }
163 
164 bool ReadOnlyPartPrivate::openLocalFile()
165 {
166  Q_Q(ReadOnlyPart);
167  Q_EMIT q->started(nullptr);
168  m_bTemp = false;
169  // set the mimetype only if it was not already set (for example, by the host application)
170  if (m_arguments.mimeType().isEmpty()) {
171  // get the mimetype of the file
172  // using findByUrl() to avoid another string -> url conversion
173  QMimeDatabase db;
174  QMimeType mime = db.mimeTypeForUrl(m_url);
175  if (!mime.isDefault()) {
176  m_arguments.setMimeType(mime.name());
177  m_bAutoDetectedMime = true;
178  }
179  }
180  const bool ret = q->openFile();
181  if (ret) {
182  Q_EMIT q->setWindowCaption(m_url.toDisplayString());
183  Q_EMIT q->completed();
184  } else {
185  Q_EMIT q->canceled(QString());
186  }
187  return ret;
188 }
189 
190 void ReadOnlyPartPrivate::openRemoteFile()
191 {
192  Q_Q(ReadOnlyPart);
193  m_bTemp = true;
194  // Use same extension as remote file. This is important for mimetype-determination (e.g. koffice)
195  QString fileName = m_url.fileName();
196  QFileInfo fileInfo(fileName);
197  QString ext = fileInfo.completeSuffix();
198  QString extension;
199  if (!ext.isEmpty() && !m_url.hasQuery()) { // not if the URL has a query, e.g. cgi.pl?something
200  extension = QLatin1Char('.') + ext; // keep the '.'
201  }
202  QTemporaryFile tempFile(QDir::tempPath() + QLatin1Char('/') + m_metaData.pluginId() + QLatin1String("XXXXXX") + extension);
203  tempFile.setAutoRemove(false);
204  tempFile.open();
205  m_file = tempFile.fileName();
206 
207  QUrl destURL = QUrl::fromLocalFile(m_file);
208  KIO::JobFlags flags = m_showProgressInfo ? KIO::DefaultFlags : KIO::HideProgressInfo;
209  flags |= KIO::Overwrite;
210  m_job = KIO::file_copy(m_url, destURL, 0600, flags);
211  m_job->setFinishedNotificationHidden(true);
212  KJobWidgets::setWindow(m_job, q->widget());
213  Q_EMIT q->started(m_job);
214 
215  QObject::connect(m_job, &KJob::result, q, [this](KJob *job) {
216  slotJobFinished(job);
217  });
218  QObject::connect(m_job, &KIO::FileCopyJob::mimeTypeFound, q, [this](KIO::Job *job, const QString &mimeType) {
219  slotGotMimeType(job, mimeType);
220  });
221 }
222 
224 {
225  Q_D(ReadOnlyPart);
226 
227  if (d->m_statJob) {
228  // qDebug() << "Aborting job" << d->m_statJob;
229  d->m_statJob->kill();
230  d->m_statJob = nullptr;
231  }
232  if (d->m_job) {
233  // qDebug() << "Aborting job" << d->m_job;
234  d->m_job->kill();
235  d->m_job = nullptr;
236  }
237 }
238 
240 {
241  Q_D(ReadOnlyPart);
242 
243  abortLoad(); // just in case
244 
245  d->m_arguments = KParts::OpenUrlArguments();
246  if (!d->m_closeUrlFromOpenUrl) {
247  setUrl(QUrl());
248  }
249 
250  if (d->m_bTemp) {
251  QFile::remove(d->m_file);
252  d->m_bTemp = false;
253  }
254  // It always succeeds for a read-only part,
255  // but the return value exists for reimplementations
256  // (e.g. pressing cancel for a modified read-write part)
257  return true;
258 }
259 
260 void ReadOnlyPartPrivate::slotStatJobFinished(KJob *job)
261 {
262  Q_ASSERT(job == m_statJob);
263  m_statJob = nullptr;
264 
265  // We could emit canceled on error, but we haven't even emitted started yet,
266  // this could maybe confuse some apps? So for now we'll just fallback to KIO::get
267  // and error again. Well, maybe this even helps with wrong stat results.
268  if (!job->error()) {
269  const QUrl localUrl = static_cast<KIO::StatJob *>(job)->mostLocalUrl();
270  if (localUrl.isLocalFile()) {
271  m_file = localUrl.toLocalFile();
272  (void)openLocalFile();
273  return;
274  }
275  }
276  openRemoteFile();
277 }
278 
279 void ReadOnlyPartPrivate::slotJobFinished(KJob *job)
280 {
281  Q_Q(ReadOnlyPart);
282 
283  Q_ASSERT(job == m_job);
284  m_job = nullptr;
285  if (job->error()) {
286  Q_EMIT q->canceled(job->errorString());
287  } else {
288  if (q->openFile()) {
289  Q_EMIT q->setWindowCaption(m_url.toDisplayString());
290  Q_EMIT q->completed();
291  } else {
292  Q_EMIT q->canceled(QString());
293  }
294  }
295 }
296 
297 void ReadOnlyPartPrivate::slotGotMimeType(KIO::Job *job, const QString &mime)
298 {
299  // qDebug() << mime;
300  Q_ASSERT(job == m_job);
301  Q_UNUSED(job)
302  // set the mimetype only if it was not already set (for example, by the host application)
303  if (m_arguments.mimeType().isEmpty()) {
304  m_arguments.setMimeType(mime);
305  m_bAutoDetectedMime = true;
306  }
307 }
308 
310 {
311  Q_D(ReadOnlyPart);
312 
313  if (event->activated()) {
314  if (!d->m_url.isEmpty()) {
315  // qDebug() << d->m_url;
316  Q_EMIT setWindowCaption(d->m_url.toDisplayString());
317  } else {
319  }
320  }
321 }
322 
323 bool ReadOnlyPart::openStream(const QString &mimeType, const QUrl &url)
324 {
325  Q_D(ReadOnlyPart);
326 
327  OpenUrlArguments args = d->m_arguments;
328  if (!closeUrl()) {
329  return false;
330  }
331  d->m_arguments = args;
332  setUrl(url);
333  return doOpenStream(mimeType);
334 }
335 
337 {
338  return doWriteStream(data);
339 }
340 
342 {
343  return doCloseStream();
344 }
345 
347 {
348  return findChild<KParts::BrowserExtension *>();
349 }
350 
352 {
353  Q_D(ReadOnlyPart);
354  d->m_arguments = arguments;
355  d->m_bAutoDetectedMime = arguments.mimeType().isEmpty();
356 }
357 
359 {
360  Q_D(const ReadOnlyPart);
361  return d->m_arguments;
362 }
363 
364 #include "moc_readonlypart.cpp"
virtual bool doCloseStream()
This is called by closeStream(), to indicate that all the data has been sent.
Definition: readonlypart.h:209
virtual bool doOpenStream(const QString &mimeType)
Called by openStream to initiate sending of data.
Definition: readonlypart.h:188
QMimeType mimeTypeForUrl(const QUrl &url) const const
bool remove()
Q_EMITQ_EMIT
virtual bool closeUrl()
Called when closing the current URL (for example, a document), for instance when switching to another...
void result(KJob *job)
QString scheme() const const
KJOBWIDGETS_EXPORT void setWindow(KJob *job, QWidget *widget)
QString mimeType() const
The mimetype to use when opening the url, when known by the calling application.
This event is sent to a Part when its GUI has been activated or deactivated. This is related to PartA...
bool closeStream()
Terminate the sending of data to the part.
void setArguments(const OpenUrlArguments &arguments)
Sets the arguments to use for the next openUrl() call.
void setProgressInfoEnabled(bool show)
Call this to turn off the progress info dialog used by the internal KIO job.
void setLocalFileTemporary(bool temp)
DefaultFlags
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
~ReadOnlyPart() override
Destructor.
QString tempPath()
void setUrl(const QUrl &url)
Sets the URL associated with this part.
bool isValid() const const
bool isProgressInfoEnabled() const
Returns whether the part shows the progress info dialog used by the internal KIO job.
bool isLocalFileTemporary() const
OpenUrlArguments arguments() const
virtual bool event(QEvent *e)
ReadOnlyPart(QObject *parent=nullptr)
Constructor.
void guiActivateEvent(GUIActivateEvent *event) override
Reimplemented from Part, so that the window caption is set to the current URL (decoded) when the part...
void setLocalFilePath(const QString &localFilePath)
Sets the local file path associated with this part.
bool isEmpty() const const
QUrl fromLocalFile(const QString &localFile)
QString toLocalFile() const const
The Browser Extension is an extension (yes, no kidding) to KParts::ReadOnlyPart, which allows a bette...
virtual bool openFile()
If the part uses the standard implementation of openUrl(), it must reimplement this to open the local...
virtual bool openUrl(const QUrl &url)
Only reimplement this if you don't want the network transparency support to download from the URL int...
virtual bool doWriteStream(const QByteArray &data)
Receive some data from the hosting application.
Definition: readonlypart.h:199
void showProgressInfo(bool show)
virtual const QMetaObject * metaObject() const const
void urlChanged(const QUrl &url)
Emitted by the part when url() changes.
const char * className() const const
FileCopyJob * file_copy(const QUrl &src, const QUrl &dest, JobFlags flags)=delete
bool openStream(const QString &mimeType, const QUrl &url)
Initiate sending data to this part.
Base class for parts.
Definition: part.h:62
QString localFilePath() const
Returns the local file path associated with this part.
bool isLocalFile() const const
void mimeTypeFound(KIO::Job *job, const QString &mimeType)
HideProgressInfo
BrowserExtension * browserExtension() const
This convenience method returns the BrowserExtension for this part, or nullptr if there isn't one.
virtual QString errorString() const
Base class for any "viewer" part.
Definition: readonlypart.h:51
int error() const
virtual QWidget * widget()
Definition: part.cpp:75
OpenUrlArguments is the set of arguments that specify how a URL should be opened by KParts::ReadOnlyP...
bool writeStream(const QByteArray &data)
Send some data to the part.
The KParts namespace,.
void setWindowCaption(const QString &caption)
Emitted by the part, to set the caption of the window(s) hosting this part.
Q_D(Todo)
static QString protocolClass(const QString &protocol)
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Tue Aug 9 2022 03:51:33 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.