KParts

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

KDE's Doxygen guidelines are available online.