File indexing completed on 2024-05-19 05:01:23

0001 /*
0002     This file is part of the KDE project.
0003 
0004     SPDX-FileCopyrightText: 2007 Trolltech ASA
0005     SPDX-FileCopyrightText: 2008 Urs Wolfer <uwolfer @ kde.org>
0006     SPDX-FileCopyrightText: 2008 Laurent Montel <montel@kde.org>
0007     SPDX-FileCopyrightText: 2009 Dawit Alemayehu <adawit@kde.org>
0008 
0009     SPDX-License-Identifier: LGPL-2.1-or-later
0010 */
0011 #ifndef WEBENGINEVIEW_H
0012 #define WEBENGINEVIEW_H
0013 
0014 #include <QPointer>
0015 #include "kf5compat.h" //For NavigationExtension
0016 #include "qtwebengine6compat.h" //For QWebEngineContextMenuRequest
0017 #include "browserarguments.h"
0018 
0019 #include <QWebEngineView>
0020 
0021 class QUrl;
0022 class WebEnginePart;
0023 
0024 class WebEngineView : public QWebEngineView
0025 {
0026     Q_OBJECT
0027 public:
0028     WebEngineView(WebEnginePart* part, QWidget* parent);
0029     ~WebEngineView() override;
0030 
0031     /**
0032      * Same as QWebEnginePage::load, but with KParts style arguments instead.
0033      *
0034      * @see KParts::OpenUrlArguments, BrowserArguments.
0035      *
0036      * @param url     the url to load.
0037      * @param args    reference to a OpenUrlArguments object.
0038      * @param bargs   reference to a BrowserArguments object.
0039      */
0040     void loadUrl(const QUrl& url, const KParts::OpenUrlArguments& args, const BrowserArguments& bargs);
0041 
0042     const QWebEngineContextMenuRequest* contextMenuResult() const;
0043 
0044 protected:
0045     /**
0046      * Reimplemented for internal reasons, the API is not affected.
0047      *
0048      * @see QWidget::contextMenuEvent
0049      * @internal
0050      */
0051     void contextMenuEvent(QContextMenuEvent*) override;
0052 
0053     /**
0054      * @brief Improve drag and drop functionality provided by `QWebEngineView`
0055      *
0056      * Before Qt 5.15.5, `QWebEngineView` didn't allow to open remote URLs by drag and drop. This function, together with
0057      * dragEnterEvent(), dragMoveEvent() and m_dragAndDropHandledBySuperclass allow that.
0058      *
0059      * In Qt 5.15.5, `QWebEngineView` allows opening remote URLs by drag and drop, but forces doing so in a new tab.
0060      * This reimplemented method, instead, opens it in the current view.
0061      *
0062      * @note Implementing this function with the behavior of `QWebEngineView` from Qt 5.15.5 is impossible without resorting
0063      * to an ugly hack. The problem is that we can't know whether the dropped URL should actually be opened or not because there
0064      * can be pages (or part of them) where dropping an URL has a special meaning (for example, uploading a file). In this case,
0065      * this function shouldn't interfere with the base class implementation. Unfortunately, `QWebEngineView` doesn't provide any
0066      * way to find out whether the URL should be opened or if the drop had
0067      * another effect, so we always should rely only on the base class implementation, which isn't configurable. To trick it,
0068      * we use WebEnginePage::setDropOperationStarted() to tell the page that a drop operation has started: this changes the way
0069      * WebEnginePage::createWindow() works so that it returns the page itself rather than creating a new page. The main problem,
0070      * however, is that there's no way to find out when the drop operation has ended, so we have to resort to a crude heuristic
0071      * to decide when this happens (as described in WebEnginePage::setDropOperationStarted())
0072      *
0073      * @see m_dragAndDropHandledBySuperclass
0074      * @see acceptDragMoveEventIfPossible()
0075      * @see WebEnginePage::setDropOperationStarted():
0076      */
0077     void dropEvent(QDropEvent *e) override;
0078 
0079 #ifdef REMOTE_DND_NOT_HANDLED_BY_WEBENGINE
0080     void dragEnterEvent(QDragEnterEvent *e) override;
0081 
0082     void dragMoveEvent(QDragMoveEvent *e) override;
0083 #endif
0084 
0085     /**
0086      * Reimplemented for internal reasons, the API is not affected.
0087      *
0088      * @see QWidget::keyPressEvent
0089      * @internal
0090      */
0091     void keyPressEvent(QKeyEvent*) override;
0092 
0093     /**
0094      * Reimplemented for internal reasons, the API is not affected.
0095      *
0096      * @see QWidget::keyReleaseEvent
0097      * @internal
0098      */
0099     void keyReleaseEvent(QKeyEvent*) override;
0100 
0101     /**
0102      * Reimplemented for internal reasons, the API is not affected.
0103      *
0104      * @see QWidget::mouseReleaseEvent
0105      * @internal
0106      */
0107     void mouseReleaseEvent(QMouseEvent*) override;
0108 
0109     /**
0110      * Reimplemented for internal reasons, the API is not affected.
0111      *
0112      * @see QObject::timerEvent
0113      * @internal
0114      */
0115     void timerEvent(QTimerEvent*) override;
0116 
0117     /**
0118      * Reimplemented for internal reasons, the API is not affected.
0119      *
0120      * @see QWidget::wheelEvent
0121      * @internal
0122      */
0123     void wheelEvent(QWheelEvent*) override;
0124 
0125 private Q_SLOTS:
0126     void slotConfigureWebShortcuts();
0127     void slotStopAutoScroll();
0128 
0129 private:
0130     void editableContentActionPopupMenu(KParts::NavigationExtension::ActionGroupMap&);
0131     void selectActionPopupMenu(KParts::NavigationExtension::ActionGroupMap&);
0132     void linkActionPopupMenu(KParts::NavigationExtension::ActionGroupMap&);
0133     void partActionPopupMenu(KParts::NavigationExtension::ActionGroupMap &);
0134     void multimediaActionPopupMenu(KParts::NavigationExtension::ActionGroupMap&);
0135     void addSearchActions(QList<QAction*>& selectActions, QWebEngineView*);
0136 
0137     //TODO KF6: when dropping compatibility with KF5, remove these and use m_result directly
0138     QWebEngineContextMenuRequest* result();
0139     const QWebEngineContextMenuRequest* result() const;
0140 
0141     KActionCollection* m_actionCollection;
0142 #if QT_VERSION_MAJOR < 6
0143     QWebEngineContextMenuRequest m_result;
0144 #else
0145     QPointer<QWebEngineContextMenuRequest> m_result = nullptr;
0146 #endif
0147     QPointer<WebEnginePart> m_part;
0148 
0149     qint32 m_autoScrollTimerId;
0150     qint32 m_verticalAutoScrollSpeed;
0151     qint32 m_horizontalAutoScrollSpeed;
0152 
0153     QHash<QString, QChar> m_duplicateLinkElements;
0154     QMenu *m_spellCheckMenu;
0155 
0156 #ifdef REMOTE_DND_NOT_HANDLED_BY_WEBENGINE
0157     /**
0158      * @brief Whether a drop enter or move event should be accepted even if the superclass wants to reject it
0159      *
0160      * If the event hasn't already been accepted, it contains urls and Konqueror has been configured to allow opening
0161      * remote URLs by drag & drop, the event is accepted and #m_dragAndDropHandledBySuperclass is set to @c true;
0162      * otherwise the variable is set to @c false
0163      * @note This function should only be called from dragEnterEvent() or dragMoveEvent()
0164      *
0165      * @param e the event, which should have already been passed to `QWebEngineView::dragEnterEvent` or
0166      * `QWebEngineView::dragMoveEvent`, according to which method called this.
0167      */
0168     void acceptDragMoveEventIfPossible(QDragMoveEvent *e);
0169 
0170     /**
0171      * @brief Whether a drop action should be handled by `QWebEngineView` or not
0172      *
0173      * `QWebEngineView` rejects drop actions except for some cases, in particular local URLs. However,
0174      * since its documentation doesn't explicitly tell what it accepts and what it rejects, a way to keep
0175      * trace of whether WebEngineView should handle the drop action itself or not must be used. This is
0176      * the scope of this variable: if the drop action was rejected by `QWebEngine` but accepted by
0177      * acceptDragMoveEventIfPossible, this variable is set to @c false; otherwise it's set to @c true.
0178      */
0179     bool m_dragAndDropHandledBySuperclass = true;
0180 #endif
0181 };
0182 
0183 #endif // WEBENGINEVIEW_H