File indexing completed on 2024-12-08 06:41:29
0001 /* 0002 This file is part of the KDE project 0003 SPDX-FileCopyrightText: 1998, 1999 Torben Weis <weis@kde.org> 0004 SPDX-FileCopyrightText: 1999-2006 David Faure <faure@kde.org> 0005 SPDX-FileCopyrightText: 2022 Harald Sitter <sitter@kde.org> 0006 0007 SPDX-License-Identifier: LGPL-2.0-or-later 0008 */ 0009 0010 #ifndef KSERVICE_H 0011 #define KSERVICE_H 0012 0013 #include "kserviceaction.h" 0014 #include <QCoreApplication> 0015 #include <QStringList> 0016 #include <QVariant> 0017 #include <kserviceconversioncheck_p.h> 0018 #include <ksycocaentry.h> 0019 0020 #include <optional> 0021 0022 class QDataStream; 0023 class KDesktopFile; 0024 class QWidget; 0025 0026 class KServicePrivate; 0027 0028 /** 0029 * @class KService kservice.h <KService> 0030 * 0031 * Represents an installed application. 0032 * 0033 * To obtain a KService instance for a specific application you typically use serviceByDesktopName(), e.g.: 0034 * 0035 * @code 0036 * KService::Ptr service = KService::serviceByDesktopName("org.kde.kate"); 0037 * @endcode 0038 * 0039 * Other typical usage would be in combination with KApplicationTrader to obtain e.g. the default application for a given file type. 0040 * 0041 * @see <a href="https://specifications.freedesktop.org/desktop-entry-spec/latest/">Desktop Entry Specification</a> 0042 */ 0043 class KSERVICE_EXPORT KService : public KSycocaEntry 0044 { 0045 public: 0046 /** 0047 * A shared data pointer for KService. 0048 */ 0049 typedef QExplicitlySharedDataPointer<KService> Ptr; 0050 /** 0051 * A list of shared data pointers for KService. 0052 */ 0053 typedef QList<Ptr> List; 0054 0055 /** 0056 * Construct a temporary service with a given name, exec-line and icon. 0057 * @param name the name of the service 0058 * @param exec the executable 0059 * @param icon the name of the icon 0060 */ 0061 KService(const QString &name, const QString &exec, const QString &icon); 0062 0063 /** 0064 * Construct a service and take all information from a .desktop file. 0065 * 0066 * @param fullpath Full path to the .desktop file. 0067 */ 0068 explicit KService(const QString &fullpath); 0069 0070 /** 0071 * Construct a service and take all information from a desktop file. 0072 * @param config the desktop file to read 0073 * @param optional relative path to store for findByName 0074 */ 0075 explicit KService(const KDesktopFile *config, const QString &entryPath = QString()); 0076 0077 KService(const KService &other); 0078 0079 ~KService() override; 0080 0081 /** 0082 * Whether this service is an application 0083 * @return true if this service is an application, i.e. it has Type=Application in its 0084 * .desktop file and exec() will not be empty. 0085 */ 0086 bool isApplication() const; 0087 0088 /** 0089 * Returns the executable. 0090 * @return the command that the service executes, 0091 * or QString() if not set 0092 */ 0093 QString exec() const; 0094 0095 /** 0096 * Returns the name of the icon. 0097 * @return the icon associated with the service, 0098 * or QString() if not set 0099 */ 0100 QString icon() const; 0101 /** 0102 * Checks whether the application should be run in a terminal. 0103 * 0104 * This corresponds to `Terminal=true` in the .desktop file. 0105 * 0106 * @return @c true if the application should be run in a terminal. 0107 */ 0108 bool terminal() const; 0109 0110 /** 0111 * Returns any options associated with the terminal the application 0112 * runs in, if it requires a terminal. 0113 * 0114 * The application must be a TTY-oriented program. 0115 * @return the terminal options, 0116 * or QString() if not set 0117 */ 0118 QString terminalOptions() const; 0119 0120 /** 0121 * Returns @c true if the application indicates that it's preferred to run 0122 * on a discrete graphics card, otherwise return @c false. 0123 * 0124 * In releases older than 5.86, this method checked for the @c X-KDE-RunOnDiscreteGpu 0125 * key in the .desktop file represented by this service; starting from 5.86 this method 0126 * now also checks for @c PrefersNonDefaultGPU key (added to the Freedesktop.org desktop 0127 * entry spec in version 1.4 of the spec). 0128 * 0129 * @since 5.30 0130 */ 0131 bool runOnDiscreteGpu() const; 0132 0133 /** 0134 * @brief Checks whether the application needs to run under a different UID. 0135 * @return @c true if the application needs to run under a different UID. 0136 * @see username() 0137 */ 0138 bool substituteUid() const; 0139 /** 0140 * Returns the user name if the application runs with a 0141 * different user id. 0142 * @return the username under which the service has to be run, 0143 * or QString() if not set 0144 * @see substituteUid() 0145 */ 0146 QString username() const; 0147 0148 /** 0149 * Returns the filename of the desktop entry without any 0150 * extension, e.g. "org.kde.kate" 0151 * @return the name of the desktop entry without path or extension, 0152 * or QString() if not set 0153 */ 0154 QString desktopEntryName() const; 0155 0156 /** 0157 * Returns the menu ID of the application desktop entry. 0158 * The menu ID is used to add or remove the entry to a menu. 0159 * @return the menu ID 0160 */ 0161 QString menuId() const; 0162 0163 /** 0164 * Returns a normalized ID suitable for storing in configuration files. 0165 * It will be based on the menu-id when available and otherwise falls 0166 * back to entryPath() 0167 * @return the storage ID 0168 */ 0169 QString storageId() const; 0170 0171 /** 0172 * @return the working directory to run the program in, 0173 * or QString() if not set 0174 * @since 5.63 0175 */ 0176 QString workingDirectory() const; 0177 0178 /** 0179 * Returns the descriptive comment for the application, if there is one. 0180 * @return the descriptive comment for the application, or QString() 0181 * if not set 0182 */ 0183 QString comment() const; 0184 0185 /** 0186 * Returns the generic name for the application, if there is one 0187 * (e.g. "Mail Client"). 0188 * @return the generic name, 0189 * or QString() if not set 0190 */ 0191 QString genericName() const; 0192 0193 /** 0194 * Returns the untranslated (US English) generic name 0195 * for the application, if there is one 0196 * (e.g. "Mail Client"). 0197 * @return the generic name, 0198 * or QString() if not set 0199 */ 0200 QString untranslatedGenericName() const; 0201 0202 /** 0203 * @return untranslated name for the given service 0204 * 0205 * @since 6.0 0206 */ 0207 QString untranslatedName() const; 0208 /** 0209 * Returns a list of descriptive keywords for the application, if there are any. 0210 * @return the list of keywords 0211 */ 0212 QStringList keywords() const; 0213 0214 /** 0215 * Returns a list of VFolder categories. 0216 * @return the list of VFolder categories 0217 */ 0218 QStringList categories() const; 0219 0220 /** 0221 * Returns the list of MIME types that this application supports. 0222 * Note that this doesn't include inherited MIME types, 0223 * only the MIME types listed in the .desktop file. 0224 * @since 4.8.3 0225 */ 0226 QStringList mimeTypes() const; 0227 0228 /** 0229 * Returns the list of scheme handlers this application supports. 0230 * 0231 * For example a web browser could return {"http", "https"}. 0232 * 0233 * This is taken from the x-scheme-handler MIME types 0234 * listed in the .desktop file. 0235 * 0236 * @since 6.0 0237 * 0238 */ 0239 QStringList schemeHandlers() const; 0240 0241 /** 0242 * Returns the list of protocols this application supports. 0243 * 0244 * This is taken from the x-scheme-handler MIME types 0245 * listed in the .desktop file as well as the 'X-KDE-Protocols' 0246 * entry 0247 * 0248 * For example a web browser could return {"http", "https"}. 0249 * @since 6.0 0250 */ 0251 QStringList supportedProtocols() const; 0252 0253 /** 0254 * Checks whether the application supports this MIME type 0255 * @param mimeType The name of the MIME type you are 0256 * interested in determining whether this service supports. 0257 * @since 4.6 0258 */ 0259 bool hasMimeType(const QString &mimeType) const; 0260 0261 /** 0262 * Returns the actions defined in this desktop file 0263 */ 0264 QList<KServiceAction> actions() const; 0265 0266 /** 0267 * Checks whether this application can handle several files as 0268 * startup arguments. 0269 * @return true if multiple files may be passed to this service at 0270 * startup. False if only one file at a time may be passed. 0271 */ 0272 bool allowMultipleFiles() const; 0273 0274 /** 0275 * What preference to associate with this application initially (before 0276 * the user has had any chance to define a profile for it). 0277 * The bigger the value, the stronger the preference for the application. 0278 * @return the service preference level of the application 0279 */ 0280 int initialPreference() const; 0281 0282 /** 0283 * Whether the entry should be hidden from the menu. 0284 * @return @c true to hide this application from the menu 0285 * 0286 * Such services still appear in trader queries, i.e. in 0287 * "Open With" popup menus for instance. 0288 */ 0289 bool noDisplay() const; 0290 0291 /** 0292 * Whether the application should be shown in the current desktop 0293 * (including in context menus). 0294 * @return true if the application should be shown in the current desktop. 0295 * 0296 * KApplicationTrader honors this and removes such services 0297 * from its results. 0298 * 0299 * @since 5.0 0300 */ 0301 bool showInCurrentDesktop() const; 0302 0303 /** 0304 * Whether the application should be shown on the current 0305 * platform (e.g. on xcb or on wayland). 0306 * @return @c true if the application should be shown on the current platform. 0307 * 0308 * @since 5.0 0309 */ 0310 bool showOnCurrentPlatform() const; 0311 0312 /** 0313 * The path to the documentation for this application. 0314 * @since 4.2 0315 * @return the documentation path, or QString() if not set 0316 */ 0317 QString docPath() const; 0318 0319 /** 0320 * Returns the requested property. 0321 * 0322 * @tparam T the type of the requested property. 0323 * 0324 * @param name the name of the property. 0325 * 0326 * @since 6.0 0327 */ 0328 template<typename T> 0329 T property(const QString &name) const 0330 { 0331 KServiceConversionCheck::to_QVariant<T>(); 0332 return property(name, static_cast<QMetaType::Type>(qMetaTypeId<T>())).value<T>(); 0333 } 0334 0335 /** 0336 * Returns a path that can be used for saving changes to this 0337 * application 0338 * @return path that can be used for saving changes to this application 0339 */ 0340 QString locateLocal() const; 0341 0342 /** 0343 * @internal 0344 * Set the menu id 0345 */ 0346 void setMenuId(const QString &menuId); 0347 /** 0348 * @internal 0349 * Sets whether to use a terminal or not 0350 */ 0351 void setTerminal(bool b); 0352 /** 0353 * @internal 0354 * Sets the terminal options to use 0355 */ 0356 void setTerminalOptions(const QString &options); 0357 0358 /** 0359 * Overrides the "Exec=" line of the service. 0360 * 0361 * If @ref exec is not empty, its value will override the one 0362 * the one set when this application was created. 0363 * 0364 * Please note that @ref entryPath is also cleared so the application 0365 * will no longer be associated with a specific config file. 0366 * 0367 * @internal 0368 * @since 4.11 0369 */ 0370 void setExec(const QString &exec); 0371 0372 /** 0373 * Overrides the "Path=" line of the application. 0374 * 0375 * If @ref workingDir is not empty, its value will override 0376 * the one set when this application was created. 0377 * 0378 * Please note that @ref entryPath is also cleared so the application 0379 * will no longer be associated with a specific config file. 0380 * 0381 * @internal 0382 * @param workingDir 0383 * @since 5.79 0384 */ 0385 void setWorkingDirectory(const QString &workingDir); 0386 0387 /** 0388 * Find a application based on its path as returned by entryPath(). 0389 * It's usually better to use serviceByStorageId() instead. 0390 * 0391 * @param _path the path of the configuration file 0392 * @return a pointer to the requested application or @c nullptr if the application is 0393 * unknown. 0394 * @em Very @em important: Don't store the result in a KService* ! 0395 */ 0396 static Ptr serviceByDesktopPath(const QString &_path); 0397 0398 /** 0399 * Find an application by the name of its desktop file, not depending on 0400 * its actual location (as long as it's under the applications or application 0401 * directories). For instance "konqbrowser" or "kcookiejar". Note that 0402 * the ".desktop" extension is implicit. 0403 * 0404 * This is the recommended method (safe even if the user moves stuff) 0405 * but note that it assumes that no two entries have the same filename. 0406 * 0407 * @param _name the name of the configuration file 0408 * @return a pointer to the requested application or @c nullptr if the application is 0409 * unknown. 0410 * @em Very @em important: Don't store the result in a KService* ! 0411 */ 0412 static Ptr serviceByDesktopName(const QString &_name); 0413 0414 /** 0415 * Find a application by its menu-id 0416 * 0417 * @param _menuId the menu id of the application 0418 * @return a pointer to the requested application or @c nullptr if the application is 0419 * unknown. 0420 * @em Very @em important: Don't store the result in a KService* ! 0421 */ 0422 static Ptr serviceByMenuId(const QString &_menuId); 0423 0424 /** 0425 * Find a application by its storage-id or desktop-file path. This 0426 * function will try very hard to find a matching application. 0427 * 0428 * @param _storageId the storage id or desktop-file path of the application 0429 * @return a pointer to the requested application or @c nullptr if the application is 0430 * unknown. 0431 * @em Very @em important: Don't store the result in a KService* ! 0432 */ 0433 static Ptr serviceByStorageId(const QString &_storageId); 0434 0435 /** 0436 * Returns the whole list of applications. 0437 * 0438 * Useful for being able to 0439 * to display them in a list box, for example. 0440 * More memory consuming than the ones above, don't use unless 0441 * really necessary. 0442 * @return the list of all applications 0443 */ 0444 static List allServices(); 0445 0446 /** 0447 * Returns a path that can be used to create a new KService based 0448 * on @p suggestedName. 0449 * @param showInMenu @c true, if the application should be shown in the KDE menu 0450 * @c false, if the application should be hidden from the menu 0451 * This argument isn't used anymore, use `NoDisplay=true` to hide the application. 0452 * @param suggestedName name to base the file on, if an application with such a 0453 * name already exists, a suffix will be added to make it unique 0454 * (e.g. foo.desktop, foo-1.desktop, foo-2.desktop). 0455 * @param menuId If provided, menuId will be set to the menu id to use for 0456 * the KService 0457 * @param reservedMenuIds If provided, the path and menu id will be chosen 0458 * in such a way that the new menu id does not conflict with any 0459 * of the reservedMenuIds 0460 * @return The path to use for the new KService. 0461 */ 0462 static QString newServicePath(bool showInMenu, const QString &suggestedName, QString *menuId = nullptr, const QStringList *reservedMenuIds = nullptr); 0463 0464 /** 0465 * @brief A desktop file name that this application is an alias for. 0466 * 0467 * This is used when a `NoDisplay` application is used to enforce specific handling 0468 * for an application. In that case the `NoDisplay` application is an `AliasFor` another 0469 * application and be considered roughly equal to the `AliasFor` application (which should 0470 * not be `NoDisplay=true`) 0471 * For example Okular supplies a desktop file for each supported format (e.g. PDF), all 0472 * of which `NoDisplay` and it is merely there to selectively support specific file formats. 0473 * A UI may choose to display the aliased entry org.kde.okular instead of the NoDisplay entries. 0474 * 0475 * @since 5.96 0476 * 0477 * @return QString desktopName of the aliased application (excluding .desktop suffix) 0478 */ 0479 QString aliasFor() const; 0480 0481 /** 0482 * Returns the value of StartupNotify for this service. 0483 * 0484 * If the service doesn't define a value nullopt is returned. 0485 * 0486 * See StartupNotify in the <a href="https://specifications.freedesktop.org/desktop-entry-spec/latest/">Desktop Entry Specification</a>. 0487 * 0488 * @since 6.0 0489 */ 0490 std::optional<bool> startupNotify() const; 0491 0492 private: 0493 friend class KBuildServiceFactory; 0494 0495 QVariant property(const QString &_name, QMetaType::Type t) const; 0496 0497 /// @internal for KBuildSycoca only 0498 struct KSERVICE_NO_EXPORT ServiceTypeAndPreference { 0499 ServiceTypeAndPreference() 0500 : preference(-1) 0501 , serviceType() 0502 { 0503 } 0504 ServiceTypeAndPreference(int pref, const QString &servType) 0505 : preference(pref) 0506 , serviceType(servType) 0507 { 0508 } 0509 int preference; 0510 QString serviceType; // or MIME type 0511 }; 0512 /// @internal for KBuildSycoca only 0513 QList<ServiceTypeAndPreference> _k_accessServiceTypes(); 0514 0515 void setActions(const QList<KServiceAction> &actions); 0516 0517 friend QDataStream &operator>>(QDataStream &, ServiceTypeAndPreference &); 0518 friend QDataStream &operator<<(QDataStream &, const ServiceTypeAndPreference &); 0519 0520 Q_DECLARE_PRIVATE(KService) 0521 0522 friend class KServiceFactory; 0523 0524 /** 0525 * @internal 0526 * Construct a service from a stream. 0527 * The stream must already be positioned at the correct offset. 0528 */ 0529 KSERVICE_NO_EXPORT KService(QDataStream &str, int offset); 0530 }; 0531 0532 template<> 0533 KSERVICE_EXPORT QString KService::property<QString>(const QString &name) const; 0534 0535 #endif