1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2020 David Faure <faure@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6*/
7
8#ifndef KIO_APPLICATIONLAUNCHERJOB_H
9#define KIO_APPLICATIONLAUNCHERJOB_H
10
11#include "kiogui_export.h"
12#include <KJob>
13#include <KService>
14#include <QUrl>
15
16class ApplicationLauncherJobTest;
17class KDesktopFileAction;
18
19namespace KIO
20{
21class ApplicationLauncherJobPrivate;
22
23/*!
24 * \class KIO::ApplicationLauncherJob
25 * \inmodule KIOGui
26 * \inheaderfile KIO/ApplicationLauncherJob
27 *
28 * \brief ApplicationLauncherJob runs an application and watches it while running.
29 *
30 * It creates a startup notification and finishes it on success or on error (for the taskbar).
31 * It also emits an error message if necessary (e.g. "program not found").
32 *
33 * When passing multiple URLs to an application that doesn't support opening
34 * multiple files, the application will be launched once for each URL.
35 *
36 * The job finishes when the application is successfully started. At that point you can
37 * query the PID(s).
38 *
39 * For error handling, either connect to the result() signal, or for a simple messagebox on error,
40 * you can use:
41 * \code
42 * // Since 5.98 use:
43 * job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this));
44 * // For older releases use:
45 * job->setUiDelegate(new KIO::JobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this));
46 * \endcode
47 * Using JobUiDelegate (which is widgets based) also enables the feature of asking the user
48 * in case the executable or desktop file isn't marked as executable. Otherwise the job will
49 * just refuse executing such files.
50 *
51 * To invoke the open-with dialog (from KIOWidgets), construct an ApplicationLauncherJob without
52 * any arguments or with a null KService.
53 *
54 * \since 5.69
55 */
56class KIOGUI_EXPORT ApplicationLauncherJob : public KJob
57{
58public:
59 /*!
60 * Creates an ApplicationLauncherJob.
61 *
62 * \a service the service (application desktop file) to run
63 *
64 * \a parent the parent QObject
65 */
66 explicit ApplicationLauncherJob(const KService::Ptr &service, QObject *parent = nullptr);
67
68 /*!
69 * Creates an ApplicationLauncherJob.
70 *
71 * \a serviceAction the service action to run
72 *
73 * \a parent the parent QObject
74 */
75 explicit ApplicationLauncherJob(const KServiceAction &serviceAction, QObject *parent = nullptr);
76
77 /*!
78 * Creates an ApplicationLauncherJob.
79 *
80 * \since 6.0
81 */
82 explicit ApplicationLauncherJob(const KDesktopFileAction &desktopFileAction, QObject *parent = nullptr);
83
84 /*!
85 * Creates an ApplicationLauncherJob which will prompt the user for which application to use
86 * (via the open-with dialog from KIOWidgets).
87 *
88 * \a parent the parent QObject
89 *
90 * \since 5.71
91 */
92 explicit ApplicationLauncherJob(QObject *parent = nullptr);
93
94 /*!
95 * Destructor
96 *
97 * Note that jobs auto-delete themselves after emitting result.
98 * Deleting/killing the job will not stop the started application.
99 */
100 ~ApplicationLauncherJob() override;
101
102 /*!
103 * Specifies the URLs to be passed to the application.
104 *
105 * \a urls list of files (local or remote) to open
106 *
107 * Note that when passing multiple URLs to an application that doesn't support opening
108 * multiple files, the application will be launched once for each URL.
109 */
110 void setUrls(const QList<QUrl> &urls);
111
112 /*!
113 * \value DeleteTemporaryFiles The URLs passed to the service will be deleted when it exits (if the URLs are local files)
114 */
115 enum RunFlag {
116 DeleteTemporaryFiles = 0x1,
117 };
118 Q_DECLARE_FLAGS(RunFlags, RunFlag)
119
120 /*!
121 * Specifies various flags.
122 *
123 * \a runFlags the flags to be set. For instance, whether the URLs are temporary files that should be deleted after execution.
124 */
125 void setRunFlags(RunFlags runFlags);
126
127 /*!
128 * Sets the file name to use in the case of downloading the file to a tempfile
129 * in order to give to a non-URL-aware application.
130 * Some apps rely on the extension to determine the MIME type of the file.
131 * Usually the file name comes from the URL, but in the case of the
132 * HTTP Content-Disposition header, we need to override the file name.
133 *
134 * \a suggestedFileName the file name
135 */
136 void setSuggestedFileName(const QString &suggestedFileName);
137
138 /*!
139 * Sets the platform-specific startup id of the application launch.
140 *
141 * \a startupId startup id, if any (otherwise "").
142 *
143 * For X11, this would be the id for the Startup Notification protocol.
144 *
145 * For Wayland, this would be the token for the XDG Activation protocol.
146 */
147 void setStartupId(const QByteArray &startupId);
148
149 /*!
150 * Starts the job.
151 *
152 * You must call this, after having done all the setters.
153 * This is (potentially) a GUI job, never use exec(), it would block user interaction.
154 */
155 void start() override;
156
157 /*!
158 * Returns the PID of the application that was started
159 *
160 * Convenience method for pids().at(0). You should only use this when specifying zero or one URL,
161 * or when you are sure that the application supports opening multiple files. Otherwise use pids().
162 * Available after the job emits result().
163 */
164 qint64 pid() const;
165
166 /*!
167 * Returns the PIDs of the applications that were started
168 *
169 * Available after the job emits result().
170 */
171 QList<qint64> pids() const;
172
173private:
174 friend class ::ApplicationLauncherJobTest;
175 /*!
176 * Blocks until the process has started.
177 */
178 bool waitForStarted();
179 KIOGUI_NO_EXPORT void emitUnauthorizedError();
180 KIOGUI_NO_EXPORT void proceedAfterSecurityChecks();
181
182 friend class ApplicationLauncherJobPrivate;
183 QScopedPointer<ApplicationLauncherJobPrivate> d;
184};
185
186} // namespace KIO
187
188#endif
189

source code of kio/src/gui/applicationlauncherjob.h