1 /*
2     This file is part of the KDE project
3     SPDX-FileCopyrightText: 1999 Simon Hausmann <hausmann@kde.org>
4     SPDX-FileCopyrightText: 1999 David Faure <faure@kde.org>
5 
6     SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #ifndef __kparts_browserextension_h__
10 #define __kparts_browserextension_h__
11 
12 #include <kparts/browserarguments.h>
13 #include <kparts/openurlarguments.h>
14 #include <kparts/readonlypart.h>
15 #include <kparts/windowargs.h>
16 
17 #include <memory>
18 
19 #include <QAction>
20 #include <qplatformdefs.h> //mode_t
21 
22 template<class Key, class T>
23 class QMap;
24 template<typename T>
25 class QList;
26 
27 class KFileItem;
28 class KFileItemList;
29 class QDataStream;
30 class QPoint;
31 
32 namespace KParts
33 {
34 class BrowserInterface;
35 
36 /**
37  * @class BrowserExtension browserextension.h <KParts/BrowserExtension>
38  *
39  * @short The Browser Extension is an extension (yes, no kidding) to
40  * KParts::ReadOnlyPart, which allows a better integration of parts
41  * with browsers (in particular Konqueror).
42  *
43  * Remember that ReadOnlyPart only has openUrl(QUrl) and a few arguments() but not much more.
44  * For full-fledged browsing, we need much more than that, including
45  * enabling/disabling of standard actions (print, copy, paste...),
46  * allowing parts to save and restore their data into the back/forward history,
47  * allowing parts to control the location bar URL, to requests URLs
48  * to be opened by the hosting browser, etc.
49  *
50  * The part developer needs to define its own class derived from BrowserExtension,
51  * to implement the virtual methods [and the standard-actions slots, see below].
52  *
53  * The way to associate the BrowserExtension with the part is to simply
54  * create the BrowserExtension as a child of the part (in QObject's terms).
55  * The hosting application will look for it automatically.
56  *
57  * Another aspect of the browser integration is that a set of standard
58  * actions are provided by the browser, but implemented by the part
59  * (for the actions it supports).
60  *
61  * The following standard actions are defined by the host of the view:
62  *
63  * [selection-dependent actions]
64  * @li @p cut : Copy selected items to clipboard and store 'not cut' in clipboard.
65  * @li @p copy : Copy selected items to clipboard and store 'cut' in clipboard.
66  * @li @p paste : Paste clipboard into view URL.
67  * @li @p pasteTo(const QUrl &) : Paste clipboard into given URL.
68  * @li @p searchProvider : Lookup selected text at default search provider
69  *
70  * [normal actions]
71  * @li None anymore.
72  *
73  *
74  * The view defines a slot with the name of the action in order to implement the action.
75  * The browser will detect the slot automatically and connect its action to it when
76  * appropriate (i.e. when the view is active).
77  *
78  *
79  * The selection-dependent actions are disabled by default and the view should
80  * enable them when the selection changes, emitting enableAction().
81  *
82  * The normal actions do not depend on the selection.
83  *
84  * A special case is the configuration slots, not connected to any action directly.
85  *
86  * [configuration slot]
87  * @li @p reparseConfiguration : Re-read configuration and apply it.
88  * @li @p disableScrolling: no scrollbars
89  */
90 class KPARTS_EXPORT BrowserExtension : public QObject // TODO KF6, rename class and header to NavigationExtension. See https://phabricator.kde.org/T12224
91 {
92     Q_OBJECT
93     Q_PROPERTY(bool urlDropHandling READ isURLDropHandlingEnabled WRITE setURLDropHandlingEnabled)
94 public:
95     /**
96      * Constructor
97      *
98      * @param parent The KParts::ReadOnlyPart that this extension ... "extends" :)
99      */
100     explicit BrowserExtension(KParts::ReadOnlyPart *parent);
101 
102     ~BrowserExtension() override;
103 
104     /**
105      * Set of flags passed via the popupMenu signal, to ask for some items in the popup menu.
106      * @see PopupFlags
107      */
108     enum PopupFlag {
109         DefaultPopupItems = 0x0000, /**< default value, no additional menu item */
110 #if KPARTS_ENABLE_DEPRECATED_SINCE(5, 27)
111         ShowNavigationItems KPARTS_ENUMERATOR_DEPRECATED_VERSION_BELATED(5, 82, 5, 27, "No effect anymore") =
112             0x0001, /**< @deprecated since 5.27, no effect anymore */
113         ShowUp KPARTS_ENUMERATOR_DEPRECATED_VERSION_BELATED(5, 82, 5, 27, "No effect anymore") = 0x0002, /**< @deprecated since 5.27, no effect anymore */
114         ShowReload KPARTS_ENUMERATOR_DEPRECATED_VERSION_BELATED(5, 82, 5, 27, "No effect anymore") = 0x0004, /**< @deprecated since 5.27, no effect anymore */
115 #endif
116         ShowBookmark = 0x0008, /**< show "add to bookmarks" (usually not done on the local filesystem) */
117         ShowCreateDirectory = 0x0010, /**<  show "create directory" (usually only done on the background of the view, or
118                                        *                      in hierarchical views like directory trees, where the new dir would be visible) */
119         ShowTextSelectionItems = 0x0020, /**< set when selecting text, for a popup that only contains text-related items. */
120         NoDeletion = 0x0040, /**< deletion, trashing and renaming not allowed (e.g. parent dir not writeable).
121                               *            (this is only needed if the protocol itself supports deletion, unlike e.g. HTTP) */
122         IsLink = 0x0080, /**< show "Bookmark This Link" and other link-related actions (linkactions merging group) */
123         ShowUrlOperations = 0x0100, /**< show copy, paste, as well as cut if NoDeletion is not set. */
124         ShowProperties = 0x200, /**< show "Properties" action (usually done by directory views) */
125     };
126 
127     /**
128      * Stores a combination of #PopupFlag values.
129      */
130     Q_DECLARE_FLAGS(PopupFlags, PopupFlag)
131 
132     /**
133      * Set the parameters to use for opening the next URL.
134      * This is called by the "hosting" application, to pass parameters to the part.
135      * @see BrowserArguments
136      */
137     virtual void setBrowserArguments(const BrowserArguments &args);
138 
139     /**
140      * Retrieve the set of parameters to use for opening the URL
141      * (this must be called from openUrl() in the part).
142      * @see BrowserArguments
143      */
144     BrowserArguments browserArguments() const;
145 
146     /**
147      * Returns the current x offset.
148      *
149      * For a scrollview, implement this using contentsX().
150      */
151     virtual int xOffset();
152     /**
153      * Returns the current y offset.
154      *
155      * For a scrollview, implement this using contentsY().
156      */
157     virtual int yOffset();
158 
159     /**
160      * Used by the browser to save the current state of the view
161      * (in order to restore it if going back in navigation).
162      *
163      * If you want to save additional properties, reimplement it
164      * but don't forget to call the parent method (probably first).
165      */
166     virtual void saveState(QDataStream &stream);
167 
168     /**
169      * Used by the browser to restore the view in the state
170      * it was when we left it.
171      *
172      * If you saved additional properties, reimplement it
173      * but don't forget to call the parent method (probably first).
174      */
175     virtual void restoreState(QDataStream &stream);
176 
177     /**
178      * Returns whether url drop handling is enabled.
179      * See setURLDropHandlingEnabled for more information about this
180      * property.
181      */
182     bool isURLDropHandlingEnabled() const;
183 
184     /**
185      * Enables or disables url drop handling. URL drop handling is a property
186      * describing whether the hosting shell component is allowed to install an
187      * event filter on the part's widget, to listen for URI drop events.
188      * Set it to true if you are exporting a BrowserExtension implementation and
189      * do not provide any special URI drop handling. If set to false you can be
190      * sure to receive all those URI drop events unfiltered. Also note that the
191      * implementation as of Konqueror installs the event filter only on the part's
192      * widget itself, not on child widgets.
193      */
194     void setURLDropHandlingEnabled(bool enable);
195 
196     void setBrowserInterface(BrowserInterface *impl);
197     BrowserInterface *browserInterface() const;
198 
199     /**
200      * @return the status (enabled/disabled) of an action.
201      * When the enableAction signal is emitted, the browserextension
202      * stores the status of the action internally, so that it's possible
203      * to query later for the status of the action, using this method.
204      */
205     bool isActionEnabled(const char *name) const;
206 
207     /**
208      * @return the text of an action, if it was set explicitly by the part.
209      * When the setActionText signal is emitted, the browserextension
210      * stores the text of the action internally, so that it's possible
211      * to query later for the text of the action, using this method.
212      */
213     QString actionText(const char *name) const;
214 
215     typedef QMap<QByteArray, QByteArray> ActionSlotMap;
216 
217 #if KPARTS_ENABLE_DEPRECATED_SINCE(5, 83)
218     /**
219      * Returns a map containing the action names as keys and corresponding
220      * SLOT()'ified method names as data entries.
221      *
222      * This is very useful for
223      * the host component, when connecting the own signals with the
224      * extension's slots.
225      * Basically you iterate over the map, check if the extension implements
226      * the slot and connect to the slot using the data value of your map
227      * iterator.
228      * Checking if the extension implements a certain slot can be done like this:
229      *
230      * \code
231      *   extension->metaObject()->slotNames().contains( actionName + "()" )
232      * \endcode
233      *
234      * (note that @p actionName is the iterator's key value if already
235      *  iterating over the action slot map, returned by this method)
236      *
237      * Connecting to the slot can be done like this:
238      *
239      * \code
240      *   connect( yourObject, SIGNAL( yourSignal() ),
241      *            extension, mapIterator.data() )
242      * \endcode
243      *
244      * (where "mapIterator" is your ActionSlotMap iterator)
245      */
246     KPARTS_DEPRECATED_VERSION(5, 83, "Use actionSlotMapPtr instead")
247     static ActionSlotMap actionSlotMap();
248 #endif
249 
250     /**
251      * @return a pointer to the static action-slot map. Preferred method to get it.
252      * The map is created if it doesn't exist yet
253      */
254     static ActionSlotMap *actionSlotMapPtr(); // TODO KF6 Rename to actionSlotMap
255 
256     /**
257      * Queries @p obj for a child object which inherits from this
258      * BrowserExtension class. Convenience method.
259      */
260     static BrowserExtension *childObject(QObject *obj);
261 
262     /**
263      * Asks the hosting browser to perform a paste (using openUrlRequestDelayed())
264      */
265     void pasteRequest();
266 
267     /**
268      * Associates a list of actions with a predefined name known by the host's popupmenu:
269      * "editactions" for actions related text editing,
270      * "linkactions" for actions related to hyperlinks,
271      * "partactions" for any other actions provided by the part
272      */
273     typedef QMap<QString, QList<QAction *>> ActionGroupMap;
274 
275 Q_SIGNALS:
276     /**
277      * Enables or disable a standard action held by the browser.
278      *
279      * See class documentation for the list of standard actions.
280      */
281     void enableAction(const char *name, bool enabled);
282 
283     /**
284      * Change the text of a standard action held by the browser.
285      * This can be used to change "Paste" into "Paste Image" for instance.
286      *
287      * See class documentation for the list of standard actions.
288      */
289     void setActionText(const char *name, const QString &text);
290 
291     /**
292      * Asks the host (browser) to open @p url.
293      * To set a reload, the x and y offsets, the service type etc., fill in the
294      * appropriate fields in the @p args structure.
295      * Hosts should not connect to this signal but to openUrlRequestDelayed().
296      */
297     void openUrlRequest(const QUrl &url,
298                         const KParts::OpenUrlArguments &arguments = KParts::OpenUrlArguments(),
299                         const KParts::BrowserArguments &browserArguments = KParts::BrowserArguments());
300 
301     /**
302      * This signal is emitted when openUrlRequest() is called, after a 0-seconds timer.
303      * This allows the caller to terminate what it's doing first, before (usually)
304      * being destroyed. Parts should never use this signal, hosts should only connect
305      * to this signal.
306      */
307     void openUrlRequestDelayed(const QUrl &url, const KParts::OpenUrlArguments &arguments, const KParts::BrowserArguments &browserArguments);
308 
309     /**
310      * Tells the hosting browser that the part opened a new URL (which can be
311      * queried via KParts::Part::url().
312      *
313      * This helps the browser to update/create an entry in the history.
314      * The part may @em not emit this signal together with openUrlRequest().
315      * Emit openUrlRequest() if you want the browser to handle a URL the user
316      * asked to open (from within your part/document). This signal however is
317      * useful if you want to handle URLs all yourself internally, while still
318      * telling the hosting browser about new opened URLs, in order to provide
319      * a proper history functionality to the user.
320      * An example of usage is a html rendering component which wants to emit
321      * this signal when a child frame document changed its URL.
322      * Conclusion: you probably want to use openUrlRequest() instead.
323      */
324     void openUrlNotify();
325 
326     /**
327      * Updates the URL shown in the browser's location bar to @p url.
328      */
329     void setLocationBarUrl(const QString &url);
330 
331     /**
332      * Sets the URL of an icon for the currently displayed page.
333      */
334     void setIconUrl(const QUrl &url);
335 
336     /**
337      * Asks the hosting browser to open a new window for the given @p url
338      * and return a reference to the content part.
339      *
340      * @p arguments is optional additional information about how to open the url,
341      * @see KParts::OpenUrlArguments
342      *
343      * @p browserArguments is optional additional information for web browsers,
344      * @see KParts::BrowserArguments
345      *
346      * The request for a pointer to the part is only fulfilled/processed
347      * if the mimeType is set in the @p browserArguments.
348      * (otherwise the request cannot be processed synchronously).
349      */
350     void createNewWindow(const QUrl &url,
351                          const KParts::OpenUrlArguments &arguments = KParts::OpenUrlArguments(),
352                          const KParts::BrowserArguments &browserArguments = KParts::BrowserArguments(),
353                          const KParts::WindowArgs &windowArgs = KParts::WindowArgs(),
354                          KParts::ReadOnlyPart **part = nullptr); // TODO consider moving to BrowserHostExtension?
355 
356     /**
357      * Since the part emits the jobid in the started() signal,
358      * progress information is automatically displayed.
359      *
360      * However, if you don't use a KIO::Job in the part,
361      * you can use loadingProgress() and speedProgress()
362      * to display progress information.
363      */
364     void loadingProgress(int percent);
365     /**
366      * @see loadingProgress
367      */
368     void speedProgress(int bytesPerSecond);
369 
370     void infoMessage(const QString &);
371 
372     /**
373      * Emit this to make the browser show a standard popup menu for the files @p items.
374      *
375      * @param global global coordinates where the popup should be shown
376      * @param items list of file items which the popup applies to
377      * @param args OpenUrlArguments, mostly for metadata here
378      * @param browserArguments BrowserArguments, mostly for referrer
379      * @param flags enables/disables certain builtin actions in the popupmenu
380      * @param actionGroups named groups of actions which should be inserted into the popup, see ActionGroupMap
381      */
382     void popupMenu(const QPoint &global,
383                    const KFileItemList &items,
384                    const KParts::OpenUrlArguments &args = KParts::OpenUrlArguments(),
385                    const KParts::BrowserArguments &browserArguments = KParts::BrowserArguments(),
386                    KParts::BrowserExtension::PopupFlags flags = KParts::BrowserExtension::DefaultPopupItems,
387                    const KParts::BrowserExtension::ActionGroupMap &actionGroups = ActionGroupMap());
388 
389     /**
390      * Emit this to make the browser show a standard popup menu for the given @p url.
391      *
392      * Give as much information about this URL as possible,
393      * like @p args.mimeType and the file type @p mode
394      *
395      * @param global global coordinates where the popup should be shown
396      * @param url the URL this popup applies to
397      * @param mode the file type of the url (S_IFREG, S_IFDIR...)
398      * @param args OpenUrlArguments, set the mimetype of the URL using setMimeType()
399      * @param browserArguments BrowserArguments, mostly for referrer
400      * @param flags enables/disables certain builtin actions in the popupmenu
401      * @param actionGroups named groups of actions which should be inserted into the popup, see ActionGroupMap
402      */
403     void popupMenu(const QPoint &global,
404                    const QUrl &url,
405                    mode_t mode = static_cast<mode_t>(-1),
406                    const KParts::OpenUrlArguments &args = KParts::OpenUrlArguments(),
407                    const KParts::BrowserArguments &browserArguments = KParts::BrowserArguments(),
408                    KParts::BrowserExtension::PopupFlags flags = KParts::BrowserExtension::DefaultPopupItems,
409                    const KParts::BrowserExtension::ActionGroupMap &actionGroups = ActionGroupMap());
410 
411     /**
412      * Inform the hosting application about the current selection.
413      * Used when a set of files/URLs is selected (with full information
414      * about those URLs, including size, permissions etc.)
415      */
416     void selectionInfo(const KFileItemList &items);
417 
418 #if KPARTS_ENABLE_DEPRECATED_SINCE(5, 88)
419     /**
420      * Inform the hosting application about the current selection.
421      * Used when some text is selected.
422      * @deprecated Since 5.88, deprecated for lack of usage
423      */
424     KPARTS_DEPRECATED_VERSION(5, 88, "Deprecated for lack of usage")
425     void selectionInfo(const QString &text);
426 #endif
427 
428 #if KPARTS_ENABLE_DEPRECATED_SINCE(5, 88)
429     /**
430      * Inform the hosting application about the current selection.
431      * Used when a set of URLs is selected.
432      * @deprecated Since 5.88, use selectionInfo(KFileItemList) instead
433      */
434     KPARTS_DEPRECATED_VERSION(5, 88, "Use selectionInfo(KFileItemList) instead")
435     void selectionInfo(const QList<QUrl> &urls);
436 #endif
437 
438     /**
439      * Inform the hosting application that the user moved the mouse over an item.
440      * Used when the mouse is on an URL.
441      */
442     void mouseOverInfo(const KFileItem &item);
443 
444     /**
445      * Ask the hosting application to add a new HTML (aka Mozilla/Netscape)
446      * SideBar entry.
447      */
448     void addWebSideBar(const QUrl &url, const QString &name);
449 
450     /**
451      * Ask the hosting application to move the top level widget.
452      */
453     void moveTopLevelWidget(int x, int y);
454 
455     /**
456      * Ask the hosting application to resize the top level widget.
457      */
458     void resizeTopLevelWidget(int w, int h);
459 
460     /**
461      * Ask the hosting application to focus @p part.
462      */
463     void requestFocus(KParts::ReadOnlyPart *part);
464 
465     /**
466      * Tell the host (browser) about security state of current page
467      * enum PageSecurity { NotCrypted, Encrypted, Mixed };
468      */
469     void setPageSecurity(int);
470 
471     /**
472      * Inform the host about items that have been removed.
473      */
474     void itemsRemoved(const KFileItemList &items);
475 
476 private Q_SLOTS:
477     void slotCompleted();
478     void slotOpenUrlRequest(const QUrl &url,
479                             const KParts::OpenUrlArguments &arguments = KParts::OpenUrlArguments(),
480                             const KParts::BrowserArguments &browserArguments = KParts::BrowserArguments());
481 
482     void slotEmitOpenUrlRequestDelayed();
483     void slotEnableAction(const char *, bool);
484     void slotSetActionText(const char *, const QString &);
485 
486 public:
487     typedef QMap<QByteArray, int> ActionNumberMap;
488 
489 private:
490     std::unique_ptr<class BrowserExtensionPrivate> const d;
491 };
492 
493 Q_DECLARE_OPERATORS_FOR_FLAGS(BrowserExtension::PopupFlags)
494 
495 }
496 
497 #endif
498