1 /*
2     This file is part of the KDE project
3     SPDX-FileCopyrightText: 1998-2009 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 KFILEITEMACTIONS_H
9 #define KFILEITEMACTIONS_H
10 
11 #include "kiowidgets_export.h"
12 #include <KService>
13 #include <kfileitem.h>
14 
15 class KFileItemListProperties;
16 class QAction;
17 class QMenu;
18 class KFileItemActionsPrivate;
19 
20 /**
21  * @class KFileItemActions kfileitemactions.h <KFileItemActions>
22  *
23  * This class creates and handles the actions for a url (or urls) in a popupmenu.
24  *
25  * This includes:
26  * @li "open with <application>" actions, but also
27  * @li user-defined actions for a .desktop file, defined in the file itself (see the desktop entry standard)
28  * @li servicemenus actions, defined in .desktop files and selected based on the MIME type of the url
29  *
30  * KFileItemActions respects Kiosk-based restrictions (see the KAuthorized
31  * namespace in the KConfig framework). In particular, the "action/openwith"
32  * action is checked when determining actions for opening files (see
33  * addOpenWithActionsTo()) and service-specific actions are checked before
34  * adding service actions to a menu (see addServiceActionsTo()).
35  *
36  * For user-defined actions in a .desktop file, the "X-KDE-AuthorizeAction" key
37  * can be used to determine which actions are checked before the user-defined
38  * action is allowed.  The action is ignored if any of the listed actions are
39  * not authorized.
40  *
41  * @note: The builtin services like mount/unmount for old-style device desktop
42  * files (which mainly concerns CDROM and Floppy drives) have been deprecated
43  * since 5.82; those menu entries were hidden long before that, since the FSDevice
44  * .desktop template file hadn't been installed for quite a while.
45  *
46  * @since 4.3
47  */
48 class KIOWIDGETS_EXPORT KFileItemActions : public QObject
49 {
50     Q_OBJECT
51 public:
52     /**
53      * Creates a KFileItemActions instance.
54      * Note that this instance must stay alive for at least as long as the popupmenu;
55      * it has the slots for the actions created by addOpenWithActionsTo/addServiceActionsTo.
56      */
57     KFileItemActions(QObject *parent = nullptr);
58 
59     /**
60      * Destructor
61      */
62     ~KFileItemActions() override;
63 
64     /**
65      * Sets all the data for the next instance of the popupmenu.
66      * @see KFileItemListProperties
67      */
68     void setItemListProperties(const KFileItemListProperties &itemList);
69 
70     /**
71      * Set the parent widget for any dialogs being shown.
72      *
73      * This should normally be your mainwindow, not a popup menu,
74      * so that it still exists even after the popup is closed
75      * (e.g. error message from KRun) and so that QAction::setStatusTip
76      * can find a statusbar, too.
77      */
78     void setParentWidget(QWidget *widget);
79 
80 #if KIOWIDGETS_ENABLE_DEPRECATED_SINCE(5, 82)
81     /**
82      * Generates the "Open With <Application>" actions, and appends them to @p menu.
83      * All actions are created as children of the menu.
84      *
85      * No actions will be added if the "openwith" Kiosk action is not authorized
86      * (see KAuthorized::authorize()).
87      *
88      * @param menu the QMenu where the actions will be added
89      * @param traderConstraint this constraint allows to exclude the current application
90      * from the "open with" list. Example: "DesktopEntryName != 'kfmclient'".
91      *
92      * @sa insertOpenWithActionsTo()
93      * @deprecated Since 5.82, use insertOpenWithActionsTo(QAction *before, QMenu *topMenu, const QStringList &excludedDesktopEntryNames) instead and pass in a
94      * nullptr for the @c before parameter
95      */
96     KIOWIDGETS_DEPRECATED_VERSION(5,
97                                   82,
98                                   "use insertOpenWithActionsTo(QAction *before, QMenu *topMenu, const QStringList &excludedDesktopEntryNames) instead and pass "
99                                   "in a nullptr for the before parameter")
100     void addOpenWithActionsTo(QMenu *menu, const QString &traderConstraint = QString());
101 #endif
102 
103 #if KIOWIDGETS_ENABLE_DEPRECATED_SINCE(5, 82)
104     /**
105      * Generates the "Open With <Application>" actions, and inserts them in @p menu,
106      * before action @p before. If @p before is nullptr or doesn't exist in the menu
107      * the actions will be appended to the menu.
108      *
109      * All actions are created as children of the menu.
110      *
111      * No actions will be added if the "openwith" Kiosk action is not authorized
112      * (see KAuthorized::authorize()).
113      *
114      * @param before the "open with" actions will be inserted before this action; if this action
115      * is nullptr or isn't available in @p topMenu, the "open with" actions will be appended
116      * @param menu the QMenu where the actions will be added
117      * @param traderConstraint this constraint allows to exclude the current application
118      * from the "open with" list. Example: "DesktopEntryName != 'kfmclient'".
119      *
120      * @since 5.78
121      * @deprecated Since 5.82, use insertOpenWithActionsTo(QAction *before, QMenu *topMenu, const QStringList &excludedDesktopEntryNames) instead
122      */
123     KIOWIDGETS_DEPRECATED_VERSION(5, 82, "use insertOpenWithActionsTo(QAction *before, QMenu *topMenu, const QStringList &excludedDesktopEntryNames) instead")
124     void insertOpenWithActionsTo(QAction *before, QMenu *topMenu, const QString &traderConstraint);
125 #endif
126 
127     /**
128      * Generates the "Open With <Application>" actions, and inserts them in @p menu,
129      * before action @p before. If @p before is nullptr or doesn't exist in the menu
130      * the actions will be appended to the menu.
131      *
132      * All actions are created as children of the menu.
133      *
134      * No actions will be added if the "openwith" Kiosk action is not authorized
135      * (see KAuthorized::authorize()).
136      *
137      * @param before the "open with" actions will be inserted before this action; if this action
138      * is nullptr or isn't available in @p topMenu, the "open with" actions will be appended
139      * @param menu the QMenu where the actions will be added
140      * @param excludedDesktopEntryNames list of desktop entry names that will not be shown
141      *
142      * @since 5.82
143      */
144     void insertOpenWithActionsTo(QAction *before, QMenu *topMenu, const QStringList &excludedDesktopEntryNames);
145 
146 #if KIOWIDGETS_ENABLE_DEPRECATED_SINCE(5, 82)
147     /**
148      * Returns an action for the preferred application only.
149      * @param traderConstraint this constraint allows to exclude the current application
150      * from the "open with" list. Example: "DesktopEntryName != 'kfmclient'".
151      * @return the action - or @c nullptr if no application was found.
152      * @deprecated Since 5.82, use the first use first entry of @c associatedApplications() to create the action instead
153      */
154     KIOWIDGETS_DEPRECATED_VERSION(5, 82, "use first entry of associatedApplications to create the action instead")
155     QAction *preferredOpenWithAction(const QString &traderConstraint);
156 #endif
157 
158 #if KIOWIDGETS_ENABLE_DEPRECATED_SINCE(5, 83)
159     /**
160      * Returns the applications associated with all the given MIME types.
161      *
162      * Helper method used internally, can also be used for similar GUIs that
163      * show the list of associated applications.
164      * Used in KParts::BrowserOpenOrSaveQuestion for example.
165      *
166      * This is basically a KMimeTypeTrader::query, but it supports multiple MIME types, and
167      * also cleans up "apparent" duplicates, such as different versions of the same
168      * application installed in parallel.
169      *
170      * The list is sorted according to the user preferences for the given MIME type(s).
171      * In case multiple MIME types appear in the URL list, the logic is:
172      * applications that on average appear earlier on the associated applications
173      * list for the given MIME types also appear earlier on the final applications list.
174      *
175      * Note that for a single MIME type there is no need to use this, you should use
176      * KMimeTypeTrader instead, e.g. query() or preferredService().
177      *
178      * This will return an empty list if the "openwith" Kiosk action is not
179      * authorized (see KAuthorized::authorize()).
180      *
181      * @param mimeTypeList the MIME types
182      * @param traderConstraint this optional constraint allows to exclude the current application
183      * from the "open with" list. Example: "DesktopEntryName != 'kfmclient'".
184      * @return the sorted list of services.
185      * @since 4.4
186      * @deprecated Since 5.83, use associatedApplications(const QStringList &) instead
187      */
188     KIOWIDGETS_DEPRECATED_VERSION(5, 83, "use associatedApplications(const QStringList &) instead")
189     static KService::List associatedApplications(const QStringList &mimeTypeList, const QString &traderConstraint);
190 #endif
191 
192     /**
193      * Returns the applications associated with all the given MIME types.
194      *
195      * This is basically a KApplicationTrader::query, but it supports multiple MIME types, and
196      * also cleans up "apparent" duplicates, such as different versions of the same
197      * application installed in parallel.
198      *
199      * The list is sorted according to the user preferences for the given MIME type(s).
200      * In case multiple MIME types appear in the URL list, the logic is:
201      * applications that on average appear earlier on the associated applications
202      * list for the given MIME types also appear earlier on the final applications list.
203      *
204      * Note that for a single MIME type there is no need to use this, you should use
205      * KApplicationTrader instead, e.g. query() or preferredService().
206      *
207      * This will return an empty list if the "openwith" Kiosk action is not
208      * authorized (see @c KAuthorized::authorize()).
209      *
210      * @param mimeTypeList the MIME types
211      * @return the sorted list of services.
212      * @since 5.83
213      */
214     static KService::List associatedApplications(const QStringList &mimeTypeList);
215 
216 #if KIOWIDGETS_ENABLE_DEPRECATED_SINCE(5, 79)
217     /**
218      * Generate the user-defined actions and submenus, and adds them to the @p menu.
219      * User-defined actions include:
220      * - builtin services like mount/unmount for old-style device desktop files
221      * - user-defined actions for a .desktop file, defined in the file itself (see the desktop entry standard)
222      * - servicemenus actions, defined in .desktop files and selected based on the MIME type of the URL
223      *
224      * When KFileItemListProperties::supportsWriting() is false, actions that modify the files are not shown.
225      * This is controlled by Require=Write in the servicemenu desktop files.
226      *
227      * Service actions that are not authorized (see KAuthorized::authorize())
228      * are not added.  For user-defined actions in a .desktop file, the
229      * "X-KDE-AuthorizeAction" key determines the Kiosk actions that are
230      * checked.
231      *
232      * All actions are created as children of the menu.
233      * @return the number of actions added
234      * @deprecated since 5.79, use addActionsTo(QMenu *menu, MenuActionSources, QList<QAction *> &, const QStringList &) instead
235      */
236     KIOWIDGETS_DEPRECATED_VERSION(5, 79, "Use addActionsTo(QMenu *menu, MenuActionSources, QList<QAction *> &, const QStringList &) instead")
237     int addServiceActionsTo(QMenu *menu);
238 #endif
239 
240 #if KIOWIDGETS_ENABLE_DEPRECATED_SINCE(5, 79)
241     /**
242      * Add actions implemented by plugins.
243      * These are defined in .desktop files or JSON in plugins using the KFileItemAction/Plugin service type,
244      * and the KAbstractFileItemActionPlugin base class.
245      *
246      * All actions are created as children of the menu.
247      * @return the number of actions added
248      *
249      * @since 5.27
250      * @deprecated since 5.79, use addActionsTo(QMenu *menu, MenuActionSources, QList<QAction *> &, const QStringList &) instead
251      */
252     KIOWIDGETS_DEPRECATED_VERSION(5, 79, "Use addActionsTo(QMenu *menu, MenuActionSources, QList<QAction *> &, const QStringList &) instead")
253     int addPluginActionsTo(QMenu *menu);
254 #endif
255 
256     enum class MenuActionSource {
257         Services = 0x1, ///< Add user defined actions and servicemenu actions (this used to include builtin
258                         ///< actions, which have been deprecated since 5.82 see class API documentation)
259         Plugins = 0x2, ///< Add actions implemented by plugins. See KAbstractFileItemActionPlugin base class.
260         All = Services | Plugins,
261     };
262     Q_DECLARE_FLAGS(MenuActionSources, MenuActionSource)
263 
264     /**
265      * This methods adds additional actions to the menu.
266      * @param menu Menu to which the actions/submenus will be added.
267      * @param sources sources from which the actions should be fetched. By default all sources are used.
268      * @param additionalActions additional actions that should be added to the "Actions" submenu or
269      * top level menu if there are less than three entries in total.
270      * @param excludeList list of action names or plugin ids that should be excluded
271      * @since 5.77
272      */
273     void addActionsTo(QMenu *menu,
274                       MenuActionSources sources = MenuActionSource::All,
275                       const QList<QAction *> &additionalActions = {},
276                       const QStringList &excludeList = {});
277 
278 Q_SIGNALS:
279     /**
280      * Emitted before the "Open With" dialog is shown
281      * This is used e.g in folderview to close the folder peek popups on invoking the "Open With" menu action
282      * @since 4.8.2
283      */
284     void openWithDialogAboutToBeShown();
285 
286     /**
287      * Forwards the errors from the KAbstractFileItemActionPlugin instances
288      * @since 5.82
289      */
290     void error(const QString &errorMessage);
291 
292 public Q_SLOTS:
293 #if KIOWIDGETS_ENABLE_DEPRECATED_SINCE(5, 79)
294     /**
295      * Slot used to execute a list of files in their respective preferred application.
296      * @param fileOpenList the list of KFileItems to open.
297      * @param traderConstraint this optional constraint allows to exclude the current application
298      * @since 4.5
299      * @deprecated Since 5.83, use use runPreferredApplications(const KFileItemList &) instead
300      */
301     KIOWIDGETS_DEPRECATED_VERSION(5, 83, "use runPreferredApplications(const KFileItemList &) instead")
302     void runPreferredApplications(const KFileItemList &fileOpenList, const QString &traderConstraint);
303 #endif
304 
305     /**
306      * Slot used to execute a list of files in their respective preferred application.
307      * @param fileOpenList the list of KFileItems to open.
308      * @since 5.83
309      */
310     void runPreferredApplications(const KFileItemList &fileOpenList);
311 
312 private:
313     KFileItemActionsPrivate *const d;
314     friend class KFileItemActionsPrivate;
315 };
316 Q_DECLARE_OPERATORS_FOR_FLAGS(KFileItemActions::MenuActionSources)
317 
318 #endif /* KFILEITEMACTIONS_H */
319