1 | /* |
2 | This file is part of the KDE project |
3 | SPDX-FileCopyrightText: 1998, 1999 Torben Weis <weis@kde.org> |
4 | SPDX-FileCopyrightText: 1999-2006 David Faure <faure@kde.org> |
5 | SPDX-FileCopyrightText: 2022 Harald Sitter <sitter@kde.org> |
6 | |
7 | SPDX-License-Identifier: LGPL-2.0-or-later |
8 | */ |
9 | |
10 | #ifndef KSERVICE_H |
11 | #define KSERVICE_H |
12 | |
13 | #include "kserviceaction.h" |
14 | #include <QCoreApplication> |
15 | #include <QStringList> |
16 | #include <QVariant> |
17 | #include <kserviceconversioncheck_p.h> |
18 | #include <ksycocaentry.h> |
19 | |
20 | #include <optional> |
21 | |
22 | class QDataStream; |
23 | class KDesktopFile; |
24 | class QWidget; |
25 | |
26 | class KServicePrivate; |
27 | |
28 | /*! |
29 | * \class KService |
30 | * \inmodule KService |
31 | * |
32 | * \brief Represents an installed application. |
33 | * |
34 | * To obtain a KService instance for a specific application you typically use serviceByDesktopName(), e.g.: |
35 | * |
36 | * \code |
37 | * KService::Ptr service = KService::serviceByDesktopName("org.kde.kate"); |
38 | * \endcode |
39 | * |
40 | * Other typical usage would be in combination with KApplicationTrader to obtain e.g. the default application for a given file type. |
41 | * |
42 | * See the \l {https://specifications.freedesktop.org/desktop-entry-spec/latest/} {Desktop Entry Specification} |
43 | */ |
44 | class KSERVICE_EXPORT KService : public KSycocaEntry |
45 | { |
46 | public: |
47 | /*! |
48 | * A shared data pointer for KService. |
49 | */ |
50 | typedef QExplicitlySharedDataPointer<KService> Ptr; |
51 | /*! |
52 | * A list of shared data pointers for KService. |
53 | */ |
54 | typedef QList<Ptr> List; |
55 | |
56 | /*! |
57 | * Construct a temporary service with a given name, exec-line and icon. |
58 | * |
59 | * \a name the name of the service |
60 | * |
61 | * \a exec the executable |
62 | * |
63 | * \a icon the name of the icon |
64 | */ |
65 | KService(const QString &name, const QString &exec, const QString &icon); |
66 | |
67 | /*! |
68 | * Construct a service and take all information from a .desktop file. |
69 | * |
70 | * \a fullpath Full path to the .desktop file. |
71 | */ |
72 | explicit KService(const QString &fullpath); |
73 | |
74 | /*! |
75 | * Construct a service and take all information from a desktop file. |
76 | * |
77 | * \a config the desktop file to read |
78 | * |
79 | * \a entryPath optional relative path to store for findByName |
80 | */ |
81 | explicit KService(const KDesktopFile *config, const QString &entryPath = QString()); |
82 | |
83 | KService(const KService &other); |
84 | |
85 | ~KService() override; |
86 | |
87 | /*! |
88 | * Whether this service is an application |
89 | * |
90 | * Returns \c true if this service is an application, i.e. it has \c Type=Application in its |
91 | * .desktop file and exec() will not be empty. |
92 | */ |
93 | bool isApplication() const; |
94 | |
95 | /*! |
96 | * Returns the command that the service executes, |
97 | * or QString() if not set |
98 | */ |
99 | QString exec() const; |
100 | |
101 | /*! |
102 | * Returns the name of the icon associated with the service, |
103 | * or QString() if not set |
104 | */ |
105 | QString icon() const; |
106 | /*! |
107 | * Checks whether the application should be run in a terminal. |
108 | * |
109 | * This corresponds to \c Terminal=true in the .desktop file. |
110 | * |
111 | * Returns \c true if the application should be run in a terminal. |
112 | */ |
113 | bool terminal() const; |
114 | |
115 | /*! |
116 | * Returns any options associated with the terminal the application |
117 | * runs in, if it requires a terminal. |
118 | * |
119 | * The application must be a TTY-oriented program. |
120 | */ |
121 | QString terminalOptions() const; |
122 | |
123 | /*! |
124 | * Returns \c true if the application indicates that it's preferred to run |
125 | * on a discrete graphics card, otherwise return \c false. |
126 | * |
127 | * In releases older than 5.86, this method checked for the \c X-KDE-RunOnDiscreteGpu |
128 | * key in the .desktop file represented by this service; starting from 5.86 this method |
129 | * now also checks for \c PrefersNonDefaultGPU key (added to the Freedesktop.org desktop |
130 | * entry spec in version 1.4 of the spec). |
131 | * |
132 | * \since KService 5.30 |
133 | */ |
134 | bool runOnDiscreteGpu() const; |
135 | |
136 | /*! |
137 | * Returns whether the application needs to run under a different UID. |
138 | * \sa username() |
139 | */ |
140 | bool substituteUid() const; |
141 | /*! |
142 | * Returns the user name if the application runs with a |
143 | * different user id. |
144 | * \sa substituteUid() |
145 | */ |
146 | QString username() const; |
147 | |
148 | /*! |
149 | * Returns the filename of the desktop entry without any |
150 | * extension, e.g. "org.kde.kate" |
151 | */ |
152 | QString desktopEntryName() const; |
153 | |
154 | /*! |
155 | * Returns the menu ID of the application desktop entry. |
156 | * |
157 | * The menu ID is used to add or remove the entry to a menu. |
158 | */ |
159 | QString () const; |
160 | |
161 | /*! |
162 | * Returns a normalized ID suitable for storing in configuration files. |
163 | * |
164 | * It will be based on the menu-id when available and otherwise falls |
165 | * back to entryPath() |
166 | */ |
167 | QString storageId() const; |
168 | |
169 | /*! |
170 | * Returns the working directory to run the program in, |
171 | * or QString() if not set |
172 | * \since 5.63 |
173 | */ |
174 | QString workingDirectory() const; |
175 | |
176 | /*! |
177 | * Returns the descriptive comment for the application, if there is one. |
178 | * if not set |
179 | */ |
180 | QString () const; |
181 | |
182 | /*! |
183 | * Returns the generic name for the application, if there is one |
184 | * (e.g. "Mail Client"). |
185 | */ |
186 | QString genericName() const; |
187 | |
188 | /*! |
189 | * Returns the untranslated (US English) generic name |
190 | * for the application, if there is one |
191 | * (e.g. "Mail Client"). |
192 | */ |
193 | QString untranslatedGenericName() const; |
194 | |
195 | /*! |
196 | * Returns the untranslated name for the given service |
197 | * |
198 | * \since 6.0 |
199 | */ |
200 | QString untranslatedName() const; |
201 | /*! |
202 | * Returns a list of descriptive keywords for the application, if there are any. |
203 | */ |
204 | QStringList keywords() const; |
205 | |
206 | /*! |
207 | * Returns a list of VFolder categories. |
208 | */ |
209 | QStringList categories() const; |
210 | |
211 | /*! |
212 | * Returns the list of MIME types that this application supports. |
213 | * |
214 | * Note that this doesn't include inherited MIME types, |
215 | * only the MIME types listed in the .desktop file. |
216 | * |
217 | * \since 4.8.3 |
218 | */ |
219 | QStringList mimeTypes() const; |
220 | |
221 | /*! |
222 | * Returns the list of scheme handlers this application supports. |
223 | * |
224 | * For example a web browser could return {"http", "https"}. |
225 | * |
226 | * This is taken from the x-scheme-handler MIME types |
227 | * listed in the .desktop file. |
228 | * |
229 | * \since 6.0 |
230 | */ |
231 | QStringList schemeHandlers() const; |
232 | |
233 | /*! |
234 | * Returns the list of protocols this application supports. |
235 | * |
236 | * This is taken from the x-scheme-handler MIME types |
237 | * listed in the .desktop file as well as the 'X-KDE-Protocols' |
238 | * entry |
239 | * |
240 | * For example a web browser could return {"http", "https"}. |
241 | * |
242 | * \since 6.0 |
243 | */ |
244 | QStringList supportedProtocols() const; |
245 | |
246 | /*! |
247 | * Returns whether the application supports this MIME type |
248 | * |
249 | * \a mimeType The name of the MIME type you are |
250 | * interested in determining whether this service supports. |
251 | * |
252 | * \since 4.6 |
253 | */ |
254 | bool hasMimeType(const QString &mimeType) const; |
255 | |
256 | /*! |
257 | * Returns the actions defined in this desktop file |
258 | * |
259 | * Only valid actions according to specification are included. |
260 | */ |
261 | QList<KServiceAction> actions() const; |
262 | |
263 | /*! |
264 | * Returns whether this application can handle several files as |
265 | * startup arguments. |
266 | */ |
267 | bool allowMultipleFiles() const; |
268 | |
269 | /*! |
270 | * Returns whether the entry should be hidden from the menu. |
271 | * |
272 | * Such services still appear in trader queries, i.e. in |
273 | * "Open With" popup menus for instance. |
274 | */ |
275 | bool noDisplay() const; |
276 | |
277 | /*! |
278 | * Returns whether the application should be shown in the current desktop |
279 | * (including in context menus). |
280 | * |
281 | * KApplicationTrader honors this and removes such services |
282 | * from its results. |
283 | * |
284 | * \since 5.0 |
285 | */ |
286 | bool showInCurrentDesktop() const; |
287 | |
288 | /*! |
289 | * Returns whether the application should be shown on the current |
290 | * platform (e.g. on xcb or on wayland). |
291 | * |
292 | * \since 5.0 |
293 | */ |
294 | bool showOnCurrentPlatform() const; |
295 | |
296 | /*! |
297 | * Returns the path to the documentation for this application. |
298 | * |
299 | * \since 4.2 |
300 | */ |
301 | QString docPath() const; |
302 | |
303 | /*! |
304 | * Returns the requested property. |
305 | * |
306 | * T the type of the requested property. |
307 | * |
308 | * \a name the name of the property. |
309 | * |
310 | * \since 6.0 |
311 | */ |
312 | template<typename T> |
313 | T property(const QString &name) const |
314 | { |
315 | KServiceConversionCheck::to_QVariant<T>(); |
316 | return property(name: name, t: static_cast<QMetaType::Type>(qMetaTypeId<T>())).value<T>(); |
317 | } |
318 | |
319 | /*! |
320 | * Returns a path that can be used for saving changes to this |
321 | * application |
322 | */ |
323 | QString locateLocal() const; |
324 | |
325 | /*! |
326 | * \internal |
327 | * Set the menu id |
328 | */ |
329 | void (const QString &); |
330 | /*! |
331 | * \internal |
332 | * Sets whether to use a terminal or not |
333 | */ |
334 | void setTerminal(bool b); |
335 | /*! |
336 | * \internal |
337 | * Sets the terminal options to use |
338 | */ |
339 | void setTerminalOptions(const QString &options); |
340 | |
341 | /*! |
342 | * Overrides the "Exec=" line of the service. |
343 | * |
344 | * If \a exec is not empty, its value will override the one |
345 | * the one set when this application was created. |
346 | * |
347 | * Please note that entryPath is also cleared so the application |
348 | * will no longer be associated with a specific config file. |
349 | * |
350 | * \internal |
351 | * \since 4.11 |
352 | */ |
353 | void setExec(const QString &exec); |
354 | |
355 | /*! |
356 | * Overrides the "Path=" line of the application. |
357 | * |
358 | * If \a workingDir is not empty, its value will override |
359 | * the one set when this application was created. |
360 | * |
361 | * Please note that entryPath is also cleared so the application |
362 | * will no longer be associated with a specific config file. |
363 | * |
364 | * \internal |
365 | * \since 5.79 |
366 | */ |
367 | void setWorkingDirectory(const QString &workingDir); |
368 | |
369 | /*! |
370 | * Find a application based on its path as returned by entryPath(). |
371 | * |
372 | * It's usually better to use serviceByStorageId() instead. |
373 | * |
374 | * \a _path the path of the configuration file |
375 | * |
376 | * Returns a pointer to the requested application or \c nullptr if the application is |
377 | * unknown. |
378 | * |
379 | * Very important: Don't store the result in a KService* ! |
380 | */ |
381 | static Ptr serviceByDesktopPath(const QString &_path); |
382 | |
383 | /*! |
384 | * Find an application by the name of its desktop file, not depending on |
385 | * its actual location (as long as it's under the applications or application |
386 | * directories). For instance "konqbrowser" or "kcookiejar". Note that |
387 | * the ".desktop" extension is implicit. |
388 | * |
389 | * This is the recommended method (safe even if the user moves stuff) |
390 | * but note that it assumes that no two entries have the same filename. |
391 | * |
392 | * \a _name the name of the configuration file |
393 | * |
394 | * Returns a pointer to the requested application or \c nullptr if the application is |
395 | * unknown. |
396 | * |
397 | * Very important: Don't store the result in a KService* ! |
398 | */ |
399 | static Ptr serviceByDesktopName(const QString &_name); |
400 | |
401 | /*! |
402 | * Find a application by its menu-id |
403 | * |
404 | * \a _menuId the menu id of the application |
405 | * |
406 | * Returns a pointer to the requested application or \c nullptr if the application is |
407 | * unknown. |
408 | * |
409 | * Very important: Don't store the result in a KService* ! |
410 | */ |
411 | static Ptr (const QString &); |
412 | |
413 | /*! |
414 | * Find a application by its storage-id or desktop-file path. This |
415 | * function will try very hard to find a matching application. |
416 | * |
417 | * \a _storageId the storage id or desktop-file path of the application |
418 | * |
419 | * Returns a pointer to the requested application or \c nullptr if the application is |
420 | * unknown. |
421 | * |
422 | * Very important: Don't store the result in a KService* ! |
423 | */ |
424 | static Ptr serviceByStorageId(const QString &_storageId); |
425 | |
426 | /*! |
427 | * Returns the whole list of applications. |
428 | * |
429 | * Useful for being able to |
430 | * to display them in a list box, for example. |
431 | * |
432 | * More memory consuming than the ones above, don't use unless |
433 | * really necessary. |
434 | */ |
435 | static List allServices(); |
436 | |
437 | /*! |
438 | * Returns a path that can be used to create a new KService based |
439 | * on \a suggestedName. |
440 | * |
441 | * \a showInMenu \c true, if the application should be shown in the KDE menu |
442 | * \c false, if the application should be hidden from the menu |
443 | * This argument isn't used anymore, use \c NoDisplay=true to hide the application. |
444 | * |
445 | * \a suggestedName name to base the file on, if an application with such a |
446 | * name already exists, a suffix will be added to make it unique |
447 | * (e.g. foo.desktop, foo-1.desktop, foo-2.desktop). |
448 | * |
449 | * \a menuId If provided, menuId will be set to the menu id to use for |
450 | * the KService |
451 | * |
452 | * \a reservedMenuIds If provided, the path and menu id will be chosen |
453 | * in such a way that the new menu id does not conflict with any |
454 | * of the reservedMenuIds |
455 | */ |
456 | static QString newServicePath(bool , const QString &suggestedName, QString * = nullptr, const QStringList * = nullptr); |
457 | |
458 | /*! |
459 | * A desktop file name that this application is an alias for. |
460 | * |
461 | * This is used when a \c NoDisplay application is used to enforce specific handling |
462 | * for an application. In that case the \c NoDisplay application is an \c AliasFor another |
463 | * application and be considered roughly equal to the \c AliasFor application (which should |
464 | * not be \c NoDisplay=true) |
465 | * |
466 | * For example Okular supplies a desktop file for each supported format (e.g. PDF), all |
467 | * of which \c NoDisplay and it is merely there to selectively support specific file formats. |
468 | * A UI may choose to display the aliased entry org.kde.okular instead of the NoDisplay entries. |
469 | * |
470 | * Returns QString desktopName of the aliased application (excluding .desktop suffix) |
471 | * |
472 | * \since 5.96 |
473 | */ |
474 | QString aliasFor() const; |
475 | |
476 | /*! |
477 | * Returns the value of StartupNotify for this service. |
478 | * |
479 | * If the service doesn't define a value nullopt is returned. |
480 | * |
481 | * See StartupNotify in the \l {https://specifications.freedesktop.org/desktop-entry-spec/latest/} {Desktop Entry Specification}. |
482 | * |
483 | * \since 6.0 |
484 | */ |
485 | std::optional<bool> startupNotify() const; |
486 | |
487 | private: |
488 | friend class KBuildServiceFactory; |
489 | |
490 | QVariant property(const QString &_name, QMetaType::Type t) const; |
491 | |
492 | void setActions(const QList<KServiceAction> &actions); |
493 | |
494 | Q_DECLARE_PRIVATE(KService) |
495 | |
496 | friend class KServiceFactory; |
497 | |
498 | /*! |
499 | * \internal |
500 | * Construct a service from a stream. |
501 | * The stream must already be positioned at the correct offset. |
502 | */ |
503 | KSERVICE_NO_EXPORT KService(QDataStream &str, int offset); |
504 | }; |
505 | |
506 | template<> |
507 | KSERVICE_EXPORT QString KService::property<QString>(const QString &name) const; |
508 | |
509 | #endif |
510 | |