1// -*- mode: c++; c-basic-offset: 2 -*-
2/* This file is part of the KDE project
3 Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
4 Copyright (C) 2006 David Faure <faure@kde.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22#ifndef KRUN_H
23#define KRUN_H
24
25#include <kio/kio_export.h>
26
27#include <QtCore/QObject>
28#include <QtCore/QTimer>
29#include <QtCore/QString>
30#include <sys/types.h>
31#include <kurl.h>
32
33class KService;
34class KStartupInfo;
35class KJob;
36namespace KIO
37{
38class Job;
39}
40
41/**
42 * To open files with their associated applications in KDE, use KRun.
43 *
44 * It can execute any desktop entry, as well as any file, using
45 * the default application or another application "bound" to the file type
46 * (or URL protocol).
47 *
48 * In that example, the mimetype of the file is not known by the application,
49 * so a KRun instance must be created. It will determine the mimetype by itself.
50 * If the mimetype is known, or if you even know the service (application) to
51 * use for this file, use one of the static methods.
52 *
53 * By default KRun uses auto deletion. It causes the KRun instance to delete
54 * itself when the it finished its task. If you allocate the KRun
55 * object on the stack you must disable auto deletion, otherwise it will crash.
56 *
57 * @short Opens files with their associated applications in KDE
58 */
59class KIO_EXPORT KRun : public QObject
60{
61 Q_OBJECT
62public:
63 /**
64 * @param url the URL of the file or directory to 'run'
65 *
66 * @param window
67 * The top-level widget of the app that invoked this object.
68 * It is used to make sure private information like passwords
69 * are properly handled per application.
70 *
71 * @param mode The @p st_mode field of <tt>struct stat</tt>. If
72 * you don't know this set it to 0.
73 *
74 * @param isLocalFile
75 * If this parameter is set to @p false then @p url is
76 * examined to find out whether it is a local URL or
77 * not. This flag is just used to improve speed, since the
78 * function KUrl::isLocalFile is a bit slow.
79 *
80 * @param showProgressInfo
81 * Whether to show progress information when determining the
82 * type of the file (i.e. when using KIO::stat and KIO::mimetype)
83 * Before you set this to false to avoid a dialog box, think about
84 * a very slow FTP server...
85 * It is always better to provide progress info in such cases.
86 * @param asn
87 * Application startup notification id, if available (otherwise "").
88 */
89 KRun(const KUrl& url, QWidget* window, mode_t mode = 0,
90 bool isLocalFile = false, bool showProgressInfo = true,
91 const QByteArray& asn = QByteArray());
92
93 /**
94 * Destructor. Don't call it yourself, since a KRun object auto-deletes
95 * itself.
96 */
97 virtual ~KRun();
98
99 /**
100 * Abort this KRun. This kills any jobs launched by it,
101 * and leads to deletion if auto-deletion is on.
102 * This is much safer than deleting the KRun (in case it's
103 * currently showing an error dialog box, for instance)
104 */
105 void abort();
106
107 /**
108 * Returns true if the KRun instance has an error.
109 * @return true when an error occurred
110 * @see error()
111 */
112 bool hasError() const;
113
114 /**
115 * Returns true if the KRun instance has finished.
116 * @return true if the KRun instance has finished
117 * @see finished()
118 */
119 bool hasFinished() const;
120
121 /**
122 * Checks whether auto delete is activated.
123 * Auto-deletion causes the KRun instance to delete itself
124 * when it finished its task.
125 * By default auto deletion is on.
126 * @return true if auto deletion is on, false otherwise
127 */
128 bool autoDelete() const;
129
130 /**
131 * Enables or disabled auto deletion.
132 * Auto deletion causes the KRun instance to delete itself
133 * when it finished its task. If you allocate the KRun
134 * object on the stack you must disable auto deletion.
135 * By default auto deletion is on.
136 * @param b true to enable auto deletion, false to disable
137 */
138 void setAutoDelete(bool b);
139
140 /**
141 * Set the preferred service for opening this URL, after
142 * its mimetype will have been found by KRun. IMPORTANT: the service is
143 * only used if its configuration says it can handle this mimetype.
144 * This is used for instance for the X-KDE-LastOpenedWith key in
145 * the recent documents list, or for the app selection in
146 * KParts::BrowserOpenOrSaveQuestion.
147 * @param desktopEntryName the desktopEntryName of the service, e.g. "kate".
148 */
149 void setPreferredService(const QString& desktopEntryName);
150
151 /**
152 * Sets whether executables, .desktop files or shell scripts should
153 * be run by KRun. This is enabled by default.
154 * @param b whether to run executable files or not.
155 * @see isExecutable()
156 */
157 void setRunExecutables(bool b);
158
159 /**
160 * Sets whether the external webbrowser setting should be honoured.
161 * This is enabled by default.
162 * This should only be disabled in webbrowser applications.
163 * @param b whether to enable the external browser or not.
164 */
165 void setEnableExternalBrowser(bool b);
166
167 /**
168 * Sets the file name to use in the case of downloading the file to a tempfile
169 * in order to give to a non-url-aware application. Some apps rely on the extension
170 * to determine the mimetype of the file. Usually the file name comes from the URL,
171 * but in the case of the HTTP Content-Disposition header, we need to override the
172 * file name.
173 */
174 void setSuggestedFileName(const QString& fileName);
175
176 /**
177 * Suggested file name given by the server (e.g. HTTP content-disposition)
178 */
179 QString suggestedFileName() const;
180
181 /**
182 * Associated window, as passed to the constructor
183 * @since 4.9.3
184 */
185 QWidget* window() const;
186
187
188 /**
189 * Open a list of URLs with a certain service (application).
190 *
191 * @param service the service to run
192 * @param urls the list of URLs, can be empty (app launched
193 * without argument)
194 * @param window The top-level widget of the app that invoked this object.
195 * @param tempFiles if true and urls are local files, they will be deleted
196 * when the application exits.
197 * @param suggestedFileName see setSuggestedFileName
198 * @param asn Application startup notification id, if any (otherwise "").
199 * @return @c true on success, @c false on error
200 */
201 static bool run(const KService& service, const KUrl::List& urls, QWidget* window,
202 bool tempFiles = false, const QString& suggestedFileName = QString(),
203 const QByteArray& asn = QByteArray());
204
205 /**
206 * Open a list of URLs with an executable.
207 *
208 * @param exec the name of the executable, for example
209 * "/usr/bin/netscape %u".
210 * Don't forget to include the %u if you know that the applications
211 * supports URLs. Otherwise, non-local urls will first be downloaded
212 * to a temp file (using kioexec).
213 * @param urls the list of URLs to open, can be empty (app launched without argument)
214 * @param window The top-level widget of the app that invoked this object.
215 * @param name the logical name of the application, for example
216 * "Netscape 4.06".
217 * @param icon the icon which should be used by the application.
218 * @param asn Application startup notification id, if any (otherwise "").
219 * @return @c true on success, @c false on error
220 */
221 static bool run(const QString& exec, const KUrl::List& urls, QWidget* window,
222 const QString& name = QString(),
223 const QString& icon = QString(),
224 const QByteArray& asn = QByteArray());
225
226 /**
227 * Open the given URL.
228 *
229 * This function is used after the mime type
230 * is found out. It will search for all services which can handle
231 * the mime type and call run() afterwards.
232 * @param url the URL to open
233 * @param mimetype the mime type of the resource
234 * @param window The top-level widget of the app that invoked this object.
235 * @param tempFile if true and url is a local file, it will be deleted
236 * when the launched application exits.
237 * @param runExecutables if false then local .desktop files,
238 * executables and shell scripts will not be run.
239 * See also isExecutable().
240 * @param suggestedFileName see setSuggestedFileName
241 * @param asn Application startup notification id, if any (otherwise "").
242 * @return @c true on success, @c false on error
243 */
244 static bool runUrl(const KUrl& url, const QString& mimetype, QWidget* window,
245 bool tempFile = false , bool runExecutables = true,
246 const QString& suggestedFileName = QString(), const QByteArray& asn = QByteArray());
247
248 /**
249 * Run the given shell command and notifies KDE of the starting
250 * of the application. If the program to be called doesn't exist,
251 * an error box will be displayed.
252 *
253 * Use only when you know the full command line. Otherwise use the other
254 * static methods, or KRun's constructor.
255 *
256 * @p cmd must be a shell command. You must not append "&"
257 * to it, since the function will do that for you.
258 * @param window The top-level widget of the app that invoked this object.
259 *
260 * @return @c true on success, @c false on error
261 */
262 static bool runCommand(const QString &cmd, QWidget* window);
263
264 /**
265 * Overload that also takes a working directory, so that a command like
266 * "kwrite file.txt" finds file.txt from the right place.
267 * @since 4.4
268 */
269 static bool runCommand(const QString &cmd, QWidget* window, const QString& workingDirectory);
270 // TODO KDE5: merge the above with 2-args runCommand, using QString()
271
272 /**
273 * Same as the other runCommand(), but it also takes the name of the
274 * binary, to display an error message in case it couldn't find it.
275 *
276 * @param cmd must be a shell command. You must not append "&"
277 * to it, since the function will do that for you.
278 * @param execName the name of the executable
279 * @param icon icon for app starting notification
280 * @param window The top-level widget of the app that invoked this object.
281 * @param asn Application startup notification id, if any (otherwise "").
282 * @return @c true on success, @c false on error
283 */
284 static bool runCommand(const QString& cmd, const QString & execName,
285 const QString & icon, QWidget* window, const QByteArray& asn = QByteArray());
286
287 /**
288 * Overload that also takes a working directory, so that a command like
289 * "kwrite file.txt" finds file.txt from the right place.
290 * @param workingDirectory the working directory for the started process. The default
291 * (if passing an empty string) is the user's document path.
292 * @since 4.4
293 */
294 static bool runCommand(const QString& cmd, const QString & execName,
295 const QString & icon, QWidget* window,
296 const QByteArray& asn, const QString& workingDirectory);
297 // TODO KDE5: merge the above with 5-args runCommand, using QString()
298
299 /**
300 * Display the Open-With dialog for those URLs, and run the chosen application.
301 * @param lst the list of applications to run
302 * @param window The top-level widget of the app that invoked this object.
303 * @param tempFiles if true and lst are local files, they will be deleted
304 * when the application exits.
305 * @param suggestedFileName see setSuggestedFileName
306 * @param asn Application startup notification id, if any (otherwise "").
307 * @return false if the dialog was canceled
308 */
309 static bool displayOpenWithDialog(const KUrl::List& lst, QWidget* window,
310 bool tempFiles = false, const QString& suggestedFileName = QString(),
311 const QByteArray& asn = QByteArray());
312
313 /**
314 * Quotes a string for the shell.
315 * An empty string will @em not be quoted.
316 *
317 * @deprecated Use KShell::quoteArg() instead. @em Note that this function
318 * behaves differently for empty arguments and returns the result
319 * differently.
320 *
321 * @param str the string to quote. The quoted string will be written here
322 */
323#ifndef KDE_NO_DEPRECATED
324 static KDE_DEPRECATED void shellQuote(QString &str);
325#endif
326
327 /**
328 * Processes a Exec= line as found in .desktop files.
329 * @param _service the service to extract information from.
330 * @param _urls The urls the service should open.
331 * @param tempFiles if true and urls are local files, they will be deleted
332 * when the application exits.
333 * @param suggestedFileName see setSuggestedFileName
334 *
335 * @return a list of arguments suitable for KProcess::setProgram().
336 */
337 static QStringList processDesktopExec(const KService &_service, const KUrl::List &_urls,
338 bool tempFiles = false,
339 const QString& suggestedFileName = QString());
340
341 /**
342 * Given a full command line (e.g. the Exec= line from a .desktop file),
343 * extract the name of the binary being run.
344 * @param execLine the full command line
345 * @param removePath if true, remove a (relative or absolute) path. E.g. /usr/bin/ls becomes ls.
346 * @return the name of the binary to run
347 */
348 static QString binaryName(const QString & execLine, bool removePath);
349
350 /**
351 * Returns whether @p serviceType refers to an executable program instead
352 * of a data file.
353 */
354 static bool isExecutable(const QString& serviceType);
355
356 /**
357 * Returns whether the @p url of @p mimetype is executable.
358 * To be executable the file must pass the following rules:
359 * -# Must reside on the local filesystem.
360 * -# Must be marked as executable for the user by the filesystem.
361 * -# The mime type must inherit application/x-executable or application/x-executable-script.
362 * To allow a script to run when the above rules are satisfied add the entry
363 * @code
364 * X-KDE-IsAlso=application/x-executable-script
365 * @endcode
366 * to the mimetype's desktop file.
367 */
368 static bool isExecutableFile(const KUrl& url, const QString &mimetype);
369
370 /**
371 * @internal
372 */
373 static bool checkStartupNotify(const QString& binName, const KService* service, bool* silent_arg,
374 QByteArray* wmclass_arg);
375
376Q_SIGNALS:
377 /**
378 * Emitted when the operation finished.
379 * This signal is emitted in all cases of completion, whether successful or with error.
380 * @see hasFinished()
381 */
382 void finished();
383 /**
384 * Emitted when the operation had an error.
385 * @see hasError()
386 */
387 void error();
388
389protected Q_SLOTS:
390 /**
391 * All following protected slots are used by subclasses of KRun!
392 */
393
394 /**
395 * This slot is called whenever the internal timer fired,
396 * in order to move on to the next step.
397 */
398 void slotTimeout(); // KDE5: rename to slotNextStep() or something like that
399
400 /**
401 * This slot is called when the scan job is finished.
402 */
403 void slotScanFinished(KJob *);
404
405 /**
406 * This slot is called when the scan job has found out
407 * the mime type.
408 */
409 void slotScanMimeType(KIO::Job *, const QString &type);
410
411 /**
412 * Call this from subclasses when you have determined the mimetype.
413 * It will call foundMimeType, but also sets up protection against deletion during message boxes.
414 * @since 4.0.2
415 */
416 void mimeTypeDetermined(const QString& mimeType);
417
418 /**
419 * This slot is called when the 'stat' job has finished.
420 */
421 virtual void slotStatResult(KJob *);
422
423protected:
424 /**
425 * All following protected methods are used by subclasses of KRun!
426 */
427
428 /**
429 * Initializes the krun object.
430 */
431 virtual void init();
432
433 /**
434 * Start scanning a file.
435 */
436 virtual void scanFile();
437
438 /**
439 * Called if the mimetype has been detected. The function runs
440 * the application associated with this mimetype.
441 * Reimplement this method to implement a different behavior,
442 * like opening the component for displaying the URL embedded.
443 *
444 * Important: call setFinished(true) once you are done!
445 * Usually at the end of the foundMimeType reimplementation, but if the
446 * reimplementation is asynchronous (e.g. uses KIO jobs) then
447 * it can be called later instead.
448 */
449 virtual void foundMimeType(const QString& type);
450
451 /**
452 * Kills the file scanning job.
453 */
454 virtual void killJob();
455
456 /**
457 * Sets the url.
458 */
459 void setUrl(const KUrl &url);
460
461 /**
462 * Returns the url.
463 */
464 KUrl url() const;
465
466 /**
467 * Sets whether an error has occurred.
468 */
469 void setError(bool error);
470
471 /**
472 * Sets whether progress information shall be shown.
473 */
474 void setProgressInfo(bool progressInfo);
475
476 /**
477 * Returns whether progress information are shown.
478 */
479 bool progressInfo() const;
480
481 /**
482 * Marks this 'KRun' instance as finished.
483 */
484 void setFinished(bool finished);
485
486 /**
487 * Sets the job.
488 */
489 void setJob(KIO::Job *job);
490
491 /**
492 * Returns the job.
493 */
494 KIO::Job* job();
495
496 /**
497 * Returns the timer object.
498 * @deprecated setFinished(true) now takes care of the timer().start(0),
499 * so this can be removed.
500 */
501#ifndef KDE_NO_DEPRECATED
502 KDE_DEPRECATED QTimer& timer();
503#endif
504
505 /**
506 * Indicate that the next action is to scan the file.
507 * @deprecated not useful in public API
508 */
509#ifndef KDE_NO_DEPRECATED
510 KDE_DEPRECATED void setDoScanFile(bool scanFile);
511#endif
512
513 /**
514 * Returns whether the file shall be scanned.
515 * @deprecated not useful in public API
516 */
517#ifndef KDE_NO_DEPRECATED
518 KDE_DEPRECATED bool doScanFile() const;
519#endif
520
521 /**
522 * Sets whether it is a directory.
523 * @deprecated typo in the name, and not useful as a public method
524 */
525#ifndef KDE_NO_DEPRECATED
526 KDE_DEPRECATED void setIsDirecory(bool isDirectory);
527#endif
528
529 /**
530 * Returns whether it is a directory.
531 */
532 bool isDirectory() const;
533
534 /**
535 * @deprecated not useful in public API
536 */
537#ifndef KDE_NO_DEPRECATED
538 KDE_DEPRECATED void setInitializeNextAction(bool initialize);
539#endif
540
541 /**
542 * @deprecated not useful in public API
543 */
544#ifndef KDE_NO_DEPRECATED
545 KDE_DEPRECATED bool initializeNextAction() const;
546#endif
547
548 /**
549 * Sets whether it is a local file.
550 */
551 void setIsLocalFile(bool isLocalFile);
552
553 /**
554 * Returns whether it is a local file.
555 */
556 bool isLocalFile() const;
557
558 /**
559 * Sets the file mode.
560 */
561 void setMode(mode_t mode);
562
563 /**
564 * Returns the file mode.
565 */
566 mode_t mode() const;
567
568private:
569 class KRunPrivate;
570 KRunPrivate* const d;
571};
572
573#endif
574