diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-02-02 14:22:12 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-02-02 14:22:12 +0100 |
commit | bd605cd2bae8a6c555bb1688573c892831b3ba9d (patch) | |
tree | 67beeb63cf353e0dffea0fc6d8cf2bd861877a6b /src/webengine | |
parent | c8bb939e7e45214f17daf8f576582e5bff2527ea (diff) | |
parent | 0cc07329495a05fc5f8532c4420bd23db662fdb6 (diff) |
Merge remote-tracking branch 'origin/5.11' into dev
Change-Id: I454bb7216b013cc9aa9ee660893fe37034fd50e1
Diffstat (limited to 'src/webengine')
-rw-r--r-- | src/webengine/api/qquickwebenginecontextmenurequest.cpp | 116 | ||||
-rw-r--r-- | src/webengine/api/qquickwebenginecontextmenurequest_p.h | 38 | ||||
-rw-r--r-- | src/webengine/api/qquickwebenginesettings.cpp | 25 | ||||
-rw-r--r-- | src/webengine/api/qquickwebenginesettings_p.h | 4 | ||||
-rw-r--r-- | src/webengine/api/qquickwebengineview.cpp | 325 | ||||
-rw-r--r-- | src/webengine/api/qquickwebengineview_p.h | 2 | ||||
-rw-r--r-- | src/webengine/api/qquickwebengineview_p_p.h | 19 | ||||
-rw-r--r-- | src/webengine/doc/src/webengineview_lgpl.qdoc | 4 | ||||
-rw-r--r-- | src/webengine/plugin/plugin.cpp | 2 | ||||
-rw-r--r-- | src/webengine/plugin/plugins.qmltypes | 66 |
10 files changed, 474 insertions, 127 deletions
diff --git a/src/webengine/api/qquickwebenginecontextmenurequest.cpp b/src/webengine/api/qquickwebenginecontextmenurequest.cpp index c53e28d93..dea89b9ab 100644 --- a/src/webengine/api/qquickwebenginecontextmenurequest.cpp +++ b/src/webengine/api/qquickwebenginecontextmenurequest.cpp @@ -42,6 +42,7 @@ QT_BEGIN_NAMESPACE +// Match MediaType enum ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaTypeNone, QQuickWebEngineContextMenuRequest::MediaTypeNone) ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaTypeImage, @@ -57,6 +58,52 @@ ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaTypeFile, ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaTypePlugin, QQuickWebEngineContextMenuRequest::MediaTypePlugin) +// Match MediaFlag enum +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaNone, + QQuickWebEngineContextMenuRequest::MediaNone) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaInError, + QQuickWebEngineContextMenuRequest::MediaInError) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaPaused, + QQuickWebEngineContextMenuRequest::MediaPaused) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaMuted, + QQuickWebEngineContextMenuRequest::MediaMuted) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaLoop, + QQuickWebEngineContextMenuRequest::MediaLoop) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaCanSave, + QQuickWebEngineContextMenuRequest::MediaCanSave) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaHasAudio, + QQuickWebEngineContextMenuRequest::MediaHasAudio) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaCanToggleControls, + QQuickWebEngineContextMenuRequest::MediaCanToggleControls) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaControls, + QQuickWebEngineContextMenuRequest::MediaControls) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaCanPrint, + QQuickWebEngineContextMenuRequest::MediaCanPrint) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaCanRotate, + QQuickWebEngineContextMenuRequest::MediaCanRotate) + +// Match EditFlag enum +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::CanDoNone, + QQuickWebEngineContextMenuRequest::CanDoNone) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::CanUndo, + QQuickWebEngineContextMenuRequest::CanUndo) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::CanRedo, + QQuickWebEngineContextMenuRequest::CanRedo) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::CanCut, + QQuickWebEngineContextMenuRequest::CanCut) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::CanCopy, + QQuickWebEngineContextMenuRequest::CanCopy) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::CanPaste, + QQuickWebEngineContextMenuRequest::CanPaste) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::CanDelete, + QQuickWebEngineContextMenuRequest::CanDelete) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::CanSelectAll, + QQuickWebEngineContextMenuRequest::CanSelectAll) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::CanTranslate, + QQuickWebEngineContextMenuRequest::CanTranslate) +ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::CanEditRichly, + QQuickWebEngineContextMenuRequest::CanEditRichly) + /*! \qmltype ContextMenuRequest \instantiates QQuickWebEngineContextMenuRequest @@ -272,4 +319,73 @@ void QQuickWebEngineContextMenuRequest::setAccepted(bool accepted) m_accepted = accepted; } +/*! + \qmlproperty flags ContextMenuRequest::mediaFlags + \readonly + \since QtWebEngine 1.7 + + The current media element's status and its available operations. + \c MediaNone if the selected web page content is not a media element. + + \value ContextMenuRequest.MediaNone + Not a media element. + \value ContextMenuRequest.MediaInError + An error occurred. + \value ContextMenuRequest.MediaPaused + Media is paused. + \value ContextMenuRequest.MediaMuted + Media is muted. + \value ContextMenuRequest.MediaLoop + Media can be looped. + \value ContextMenuRequest.MediaCanSave + Media can be saved. + \value ContextMenuRequest.MediaHasAudio + Media has audio. + \value ContextMenuRequest.MediaCanToggleControls + Media can show controls. + \value ContextMenuRequest.MediaControls + Media controls are shown. + \value ContextMenuRequest.MediaCanPrint + Media is printable. + \value ContextMenuRequest.MediaCanRotate + Media is rotatable. +*/ +QQuickWebEngineContextMenuRequest::MediaFlags QQuickWebEngineContextMenuRequest::mediaFlags() const +{ + return static_cast<QQuickWebEngineContextMenuRequest::MediaFlags>(m_data->mediaFlags()); +} + +/*! + \qmlproperty flags ContextMenuRequest::editFlags + \readonly + \since QtWebEngine 1.7 + + The available edit operations in the current context or \c CanDoNone if no actions are available. + + \value ContextMenuRequest.CanDoNone + Nothing can be done. + \value ContextMenuRequest.CanUndo + Undo is available. + \value ContextMenuRequest.CanRedo + Redo is available. + \value ContextMenuRequest.CanCut + Cut is available. + \value ContextMenuRequest.CanCopy + Copy is available. + \value ContextMenuRequest.CanPaste + Paste is available. + \value ContextMenuRequest.CanDelete + Delete is available. + \value ContextMenuRequest.CanSelectAll + Select All is available. + \value ContextMenuRequest.CanTranslate + Translate is available. + \value ContextMenuRequest.CanEditRichly + Context is richly editable. +*/ +QQuickWebEngineContextMenuRequest::EditFlags QQuickWebEngineContextMenuRequest::editFlags() const +{ + return static_cast<QQuickWebEngineContextMenuRequest::EditFlags>(m_data->editFlags()); +} + QT_END_NAMESPACE diff --git a/src/webengine/api/qquickwebenginecontextmenurequest_p.h b/src/webengine/api/qquickwebenginecontextmenurequest_p.h index 3d2de14a2..5f0b0c282 100644 --- a/src/webengine/api/qquickwebenginecontextmenurequest_p.h +++ b/src/webengine/api/qquickwebenginecontextmenurequest_p.h @@ -75,6 +75,38 @@ public: }; Q_ENUM(MediaType) + // Must match QWebEngineCore::WebEngineContextMenuData::MediaFlags: + enum MediaFlag { + MediaNone = 0x0, + MediaInError = 0x1, + MediaPaused = 0x2, + MediaMuted = 0x4, + MediaLoop = 0x8, + MediaCanSave = 0x10, + MediaHasAudio = 0x20, + MediaCanToggleControls = 0x40, + MediaControls = 0x80, + MediaCanPrint = 0x100, + MediaCanRotate = 0x200, + }; + Q_DECLARE_FLAGS(MediaFlags, MediaFlag) + + + // Must match QWebEngineCore::WebEngineContextMenuData::EditFlags: + enum EditFlag { + CanDoNone = 0x0, + CanUndo = 0x1, + CanRedo = 0x2, + CanCut = 0x4, + CanCopy = 0x8, + CanPaste = 0x10, + CanDelete = 0x20, + CanSelectAll = 0x40, + CanTranslate = 0x80, + CanEditRichly = 0x100, + }; + Q_DECLARE_FLAGS(EditFlags, EditFlag) + Q_PROPERTY(int x READ x CONSTANT FINAL) Q_PROPERTY(int y READ y CONSTANT FINAL) Q_PROPERTY(QString selectedText READ selectedText CONSTANT FINAL) @@ -86,6 +118,8 @@ public: Q_PROPERTY(QString misspelledWord READ misspelledWord CONSTANT FINAL) Q_PROPERTY(QStringList spellCheckerSuggestions READ spellCheckerSuggestions CONSTANT FINAL) Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted FINAL) + Q_PROPERTY(MediaFlags mediaFlags READ mediaFlags CONSTANT FINAL REVISION 1) + Q_PROPERTY(EditFlags editFlags READ editFlags CONSTANT FINAL REVISION 1) ~QQuickWebEngineContextMenuRequest(); int x() const; @@ -100,11 +134,15 @@ public: QStringList spellCheckerSuggestions() const; bool isAccepted() const; void setAccepted(bool accepted); + MediaFlags mediaFlags() const; + EditFlags editFlags() const; private: QQuickWebEngineContextMenuRequest(const QtWebEngineCore::WebEngineContextMenuData &data, QObject *parent = nullptr); QScopedPointer<QtWebEngineCore::WebEngineContextMenuData> m_data; bool m_accepted; + Q_FLAGS(MediaFlags) + Q_FLAGS(EditFlags) friend class QQuickWebEngineView; friend class QQuickWebEngineViewPrivate; Q_DISABLE_COPY(QQuickWebEngineContextMenuRequest) diff --git a/src/webengine/api/qquickwebenginesettings.cpp b/src/webengine/api/qquickwebenginesettings.cpp index 71b0deeca..6203f20f1 100644 --- a/src/webengine/api/qquickwebenginesettings.cpp +++ b/src/webengine/api/qquickwebenginesettings.cpp @@ -130,6 +130,9 @@ bool QQuickWebEngineSettings::javascriptCanOpenWindows() const Allows JavaScript programs to read from or write to the clipboard. Writing to the clipboard is always allowed if it is specifically requested by the user. + To enable also the pasting of clipboard content from JavaScript, + use javascriptCanPaste. + Disabled by default. */ bool QQuickWebEngineSettings::javascriptCanAccessClipboard() const @@ -426,6 +429,20 @@ bool QQuickWebEngineSettings::webRTCPublicInterfacesOnly() const } /*! + \qmlproperty bool WebEngineSettings::javascriptCanPaste + \since QtWebEngine 1.7 + + Enables JavaScript \c{execCommand("paste")}. + This also requires enabling javascriptCanAccessClipboard. + + Disabled by default. +*/ +bool QQuickWebEngineSettings::javascriptCanPaste() const +{ + return d_ptr->testAttribute(WebEngineSettings::JavascriptCanPaste); +} + +/*! \qmlproperty string WebEngineSettings::defaultTextEncoding \since QtWebEngine 1.2 @@ -667,6 +684,14 @@ void QQuickWebEngineSettings::setPlaybackRequiresUserGesture(bool on) Q_EMIT playbackRequiresUserGestureChanged(); } +void QQuickWebEngineSettings::setJavascriptCanPaste(bool on) +{ + bool wasOn = d_ptr->testAttribute(WebEngineSettings::JavascriptCanPaste); + d_ptr->setAttribute(WebEngineSettings::JavascriptCanPaste, on); + if (wasOn != on) + Q_EMIT javascriptCanPasteChanged(); +} + void QQuickWebEngineSettings::setUnknownUrlSchemePolicy(QQuickWebEngineSettings::UnknownUrlSchemePolicy policy) { WebEngineSettings::UnknownUrlSchemePolicy oldPolicy = d_ptr->unknownUrlSchemePolicy(); diff --git a/src/webengine/api/qquickwebenginesettings_p.h b/src/webengine/api/qquickwebenginesettings_p.h index 60baa7323..2911ee283 100644 --- a/src/webengine/api/qquickwebenginesettings_p.h +++ b/src/webengine/api/qquickwebenginesettings_p.h @@ -91,6 +91,7 @@ class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineSettings : public QObject { Q_PROPERTY(UnknownUrlSchemePolicy unknownUrlSchemePolicy READ unknownUrlSchemePolicy WRITE setUnknownUrlSchemePolicy NOTIFY unknownUrlSchemePolicyChanged REVISION 6 FINAL) Q_PROPERTY(bool playbackRequiresUserGesture READ playbackRequiresUserGesture WRITE setPlaybackRequiresUserGesture NOTIFY playbackRequiresUserGestureChanged REVISION 6 FINAL) Q_PROPERTY(bool webRTCPublicInterfacesOnly READ webRTCPublicInterfacesOnly WRITE setWebRTCPublicInterfacesOnly NOTIFY webRTCPublicInterfacesOnlyChanged REVISION 6 FINAL) + Q_PROPERTY(bool javascriptCanPaste READ javascriptCanPaste WRITE setJavascriptCanPaste NOTIFY javascriptCanPaste REVISION 6 FINAL) public: enum UnknownUrlSchemePolicy { @@ -131,6 +132,7 @@ public: UnknownUrlSchemePolicy unknownUrlSchemePolicy() const; bool playbackRequiresUserGesture() const; bool webRTCPublicInterfacesOnly() const; + bool javascriptCanPaste() const; void setAutoLoadImages(bool on); void setJavascriptEnabled(bool on); @@ -160,6 +162,7 @@ public: void setUnknownUrlSchemePolicy(UnknownUrlSchemePolicy policy); void setPlaybackRequiresUserGesture(bool on); void setWebRTCPublicInterfacesOnly(bool on); + void setJavascriptCanPaste(bool on); signals: void autoLoadImagesChanged(); @@ -190,6 +193,7 @@ signals: Q_REVISION(6) void unknownUrlSchemePolicyChanged(); Q_REVISION(6) void playbackRequiresUserGestureChanged(); Q_REVISION(6) void webRTCPublicInterfacesOnlyChanged(); + Q_REVISION(6) void javascriptCanPasteChanged(); private: explicit QQuickWebEngineSettings(QQuickWebEngineSettings *parentSettings = 0); diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index f49b2c6bb..19e85315b 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -190,8 +190,14 @@ void QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenu m_contextMenuData = data; QQuickWebEngineContextMenuRequest *request = new QQuickWebEngineContextMenuRequest(data); + QQmlEngine *engine = qmlEngine(q); + + // TODO: this is a workaround for QTBUG-65044 + if (!engine) + return; + // mark the object for gc by creating temporary jsvalue - qmlEngine(q)->newQObject(request); + engine->newQObject(request); Q_EMIT q->contextMenuRequested(request); if (request->isAccepted()) @@ -203,129 +209,14 @@ void QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenu if (!menu) return; - // Populate our menu - MenuItemHandler *item = 0; - if (data.isEditable() && !data.spellCheckerSuggestions().isEmpty()) { - const QPointer<QQuickWebEngineView> qRef(q); - for (int i=0; i < data.spellCheckerSuggestions().count() && i < 4; i++) { - item = new MenuItemHandler(menu); - QString replacement = data.spellCheckerSuggestions().at(i); - QObject::connect(item, &MenuItemHandler::triggered, [qRef, replacement] { qRef->replaceMisspelledWord(replacement); }); - ui()->addMenuItem(item, replacement); - } - ui()->addMenuSeparator(menu); - } - if (data.linkUrl().isValid()) { - item = new MenuItemHandler(menu); - QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::OpenLinkInThisWindow); }); - ui()->addMenuItem(item, QQuickWebEngineView::tr("Follow Link")); - } - - if (data.selectedText().isEmpty()) { - item = new MenuItemHandler(menu); - QObject::connect(item, &MenuItemHandler::triggered, q, &QQuickWebEngineView::goBack); - ui()->addMenuItem(item, QQuickWebEngineView::tr("Back"), QStringLiteral("go-previous"), q->canGoBack()); - - item = new MenuItemHandler(menu); - QObject::connect(item, &MenuItemHandler::triggered, q, &QQuickWebEngineView::goForward); - ui()->addMenuItem(item, QQuickWebEngineView::tr("Forward"), QStringLiteral("go-next"), q->canGoForward()); + QQuickContextMenuBuilder contextMenuBuilder(data, q, menu); - item = new MenuItemHandler(menu); - QObject::connect(item, &MenuItemHandler::triggered, q, &QQuickWebEngineView::reload); - ui()->addMenuItem(item, QQuickWebEngineView::tr("Reload"), QStringLiteral("view-refresh")); - - item = new MenuItemHandler(menu); - QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::ViewSource); }); - ui()->addMenuItem(item, QQuickWebEngineView::tr("View Page Source"), QStringLiteral("view-source"), adapter->canViewSource()); - } else { - item = new MenuItemHandler(menu); - QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::Copy); }); - ui()->addMenuItem(item, QQuickWebEngineView::tr("Copy")); - item = new MenuItemHandler(menu); - QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::Unselect); }); - ui()->addMenuItem(item, QQuickWebEngineView::tr("Unselect")); - } - - if (!data.linkText().isEmpty() && !data.unfilteredLinkUrl().isEmpty()) { - item = new MenuItemHandler(menu); - QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::CopyLinkToClipboard); }); - ui()->addMenuItem(item, QQuickWebEngineView::tr("Copy Link URL")); - } - if (!data.linkText().isEmpty() && data.linkUrl().isValid()) { - item = new MenuItemHandler(menu); - QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::DownloadLinkToDisk); }); - ui()->addMenuItem(item, QQuickWebEngineView::tr("Save Link")); - } - if (data.mediaUrl().isValid()) { - switch (data.mediaType()) { - case WebEngineContextMenuData::MediaTypeImage: - item = new MenuItemHandler(menu); - QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::CopyImageUrlToClipboard); }); - ui()->addMenuItem(item, QQuickWebEngineView::tr("Copy Image URL")); - item = new MenuItemHandler(menu); - QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::CopyImageToClipboard); }); - ui()->addMenuItem(item, QQuickWebEngineView::tr("Copy Image")); - item = new MenuItemHandler(menu); - QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::DownloadImageToDisk); }); - ui()->addMenuItem(item, QQuickWebEngineView::tr("Save Image")); - break; - case WebEngineContextMenuData::MediaTypeCanvas: - Q_UNREACHABLE(); // mediaUrl is invalid for canvases - break; - case WebEngineContextMenuData::MediaTypeAudio: - case WebEngineContextMenuData::MediaTypeVideo: - item = new MenuItemHandler(menu); - QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::CopyMediaUrlToClipboard); }); - ui()->addMenuItem(item, QQuickWebEngineView::tr("Copy Media URL")); - item = new MenuItemHandler(menu); - QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::DownloadMediaToDisk); }); - ui()->addMenuItem(item, QQuickWebEngineView::tr("Save Media")); - item = new MenuItemHandler(menu); - QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::ToggleMediaPlayPause); }); - ui()->addMenuItem(item, QQuickWebEngineView::tr("Toggle Play/Pause")); - item = new MenuItemHandler(menu); - QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::ToggleMediaLoop); }); - ui()->addMenuItem(item, QQuickWebEngineView::tr("Toggle Looping")); - if (data.mediaFlags() & WebEngineContextMenuData::MediaHasAudio) { - item = new MenuItemHandler(menu); - QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::ToggleMediaMute); }); - ui()->addMenuItem(item, QQuickWebEngineView::tr("Toggle Mute")); - } - if (data.mediaFlags() & WebEngineContextMenuData::MediaCanToggleControls) { - item = new MenuItemHandler(menu); - QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::ToggleMediaControls); }); - ui()->addMenuItem(item, QQuickWebEngineView::tr("Toggle Media Controls")); - } - break; - default: - break; - } - } else if (data.mediaType() == WebEngineContextMenuData::MediaTypeCanvas) { - item = new MenuItemHandler(menu); - QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::CopyImageToClipboard); }); - ui()->addMenuItem(item, QQuickWebEngineView::tr("Copy Image")); - } - if (adapter->hasInspector()) { - item = new MenuItemHandler(menu); - QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::InspectElement); }); - ui()->addMenuItem(item, QQuickWebEngineView::tr("Inspect Element")); - } - if (isFullScreenMode()) { - item = new MenuItemHandler(menu); - QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::ExitFullScreen); }); - ui()->addMenuItem(item, QQuickWebEngineView::tr("Exit Full Screen Mode")); - } + // Populate our menu + contextMenuBuilder.initMenu(); // FIXME: expose the context menu data as an attached property to make this more useful - if (contextMenuExtraItems) { - ui()->addMenuSeparator(menu); - if (QObject* menuExtras = contextMenuExtraItems->create(qmlContext(q))) { - menuExtras->setParent(menu); - QQmlListReference entries(menu, defaultPropertyName(menu), qmlEngine(q)); - if (entries.isValid()) - entries.append(menuExtras); - } - } + if (contextMenuExtraItems) + contextMenuBuilder.appendExtraItems(engine); // Now fire the popup() method on the top level menu ui()->showMenu(menu); @@ -427,6 +318,11 @@ void QQuickWebEngineViewPrivate::iconChanged(const QUrl &url) if (!faviconProvider) { QQmlEngine *engine = qmlEngine(q); + + // TODO: this is a workaround for QTBUG-65044 + if (!engine) + return; + Q_ASSERT(engine); faviconProvider = static_cast<QQuickWebEngineFaviconProvider *>( engine->imageProvider(QQuickWebEngineFaviconProvider::identifier())); @@ -1932,5 +1828,192 @@ qint64 QQuickWebEngineQuotaPermissionRequest::requestedSize() const return d_ptr->requestedSize(); } +QQuickContextMenuBuilder::QQuickContextMenuBuilder(const QtWebEngineCore::WebEngineContextMenuData &data, + QQuickWebEngineView *view, + QObject *menu) + : QtWebEngineCore::RenderViewContextMenuQt(data) + , m_view(view) + , m_menu(menu) +{ +} + +void QQuickContextMenuBuilder::appendExtraItems(QQmlEngine *engine) +{ + m_view->d_ptr->ui()->addMenuSeparator(m_menu); + if (QObject *menuExtras = m_view->d_ptr->contextMenuExtraItems->create(qmlContext(m_view))) { + menuExtras->setParent(m_menu); + QQmlListReference entries(m_menu, defaultPropertyName(m_menu), engine); + if (entries.isValid()) + entries.append(menuExtras); + } +} + +bool QQuickContextMenuBuilder::hasInspector() +{ + return m_view->d_ptr->adapter->hasInspector(); +} + +bool QQuickContextMenuBuilder::isFullScreenMode() +{ + return m_view->d_ptr->isFullScreenMode(); +} + +void QQuickContextMenuBuilder::addMenuItem(ContextMenuItem menuItem) +{ + MenuItemHandler *item = new MenuItemHandler(m_menu); + QString menuItemIcon; + QPointer<QQuickWebEngineView> thisRef(m_view); + + switch (menuItem) { + case ContextMenuItem::Back: + QObject::connect(item, &MenuItemHandler::triggered, thisRef, &QQuickWebEngineView::goBack); + menuItemIcon = QStringLiteral("go-previous"); + break; + case ContextMenuItem::Forward: + QObject::connect(item, &MenuItemHandler::triggered, thisRef, &QQuickWebEngineView::goForward); + menuItemIcon = QStringLiteral("go-next"); + break; + case ContextMenuItem::Reload: + QObject::connect(item, &MenuItemHandler::triggered, thisRef, &QQuickWebEngineView::reload); + menuItemIcon = QStringLiteral("view-refresh"); + break; + case ContextMenuItem::Cut: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::Cut); }); + menuItemIcon = QStringLiteral("Cut"); + break; + case ContextMenuItem::Copy: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::Copy); }); + menuItemIcon = QStringLiteral("Copy"); + break; + + case ContextMenuItem::Paste: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::Paste); }); + menuItemIcon = QStringLiteral("Paste"); + break; + case ContextMenuItem::Undo: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::Undo); }); + menuItemIcon = QStringLiteral("Undo"); + break; + case ContextMenuItem::Redo: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::Redo); }); + menuItemIcon = QStringLiteral("Redo"); + break; + case ContextMenuItem::SelectAll: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::SelectAll); }); + menuItemIcon = QStringLiteral("Select All"); + break; + case ContextMenuItem::PasteAndMatchStyle: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::PasteAndMatchStyle); }); + menuItemIcon = QStringLiteral("Paste And Match Style"); + break; + case ContextMenuItem::OpenLinkInNewWindow: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::OpenLinkInNewWindow); }); + break; + case ContextMenuItem::OpenLinkInNewTab: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::OpenLinkInNewTab); }); + break; + case ContextMenuItem::CopyLinkToClipboard: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::CopyLinkToClipboard); }); + break; + case ContextMenuItem::DownloadLinkToDisk: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::DownloadLinkToDisk); }); + break; + case ContextMenuItem::CopyImageToClipboard: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::CopyImageToClipboard); }); + break; + case ContextMenuItem::CopyImageUrlToClipboard: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::CopyImageUrlToClipboard); }); + break; + case ContextMenuItem::DownloadImageToDisk: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::DownloadImageToDisk); }); + break; + case ContextMenuItem::CopyMediaUrlToClipboard: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::CopyMediaUrlToClipboard); }); + break; + case ContextMenuItem::ToggleMediaControls: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::ToggleMediaControls); }); + break; + case ContextMenuItem::ToggleMediaLoop: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::ToggleMediaLoop); }); + break; + case ContextMenuItem::DownloadMediaToDisk: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::DownloadMediaToDisk); }); + break; + case ContextMenuItem::InspectElement: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::InspectElement); }); + break; + case ContextMenuItem::ExitFullScreen: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::ExitFullScreen); }); + break; + case ContextMenuItem::SavePage: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::SavePage); }); + break; + case ContextMenuItem::ViewSource: + QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::ViewSource); }); + menuItemIcon = QStringLiteral("view-source"); + break; + case ContextMenuItem::SpellingSuggestions: + for (int i=0; i < m_contextData.spellCheckerSuggestions().count() && i < 4; i++) { + item = new MenuItemHandler(m_menu); + QString replacement = m_contextData.spellCheckerSuggestions().at(i); + QObject::connect(item, &MenuItemHandler::triggered, [thisRef, replacement] { thisRef->replaceMisspelledWord(replacement); }); + m_view->d_ptr->ui()->addMenuItem(item, replacement); + } + return; + case ContextMenuItem::Separator: + thisRef->d_ptr->ui()->addMenuSeparator(m_menu); + return; + } + QString menuItemName = RenderViewContextMenuQt::getMenuItemName(menuItem); + thisRef->d_ptr->ui()->addMenuItem(item, menuItemName, menuItemIcon, isMenuItemEnabled(menuItem)); +} + +bool QQuickContextMenuBuilder::isMenuItemEnabled(ContextMenuItem menuItem) +{ + switch (menuItem) { + case ContextMenuItem::Back: + return m_view->canGoBack(); + case ContextMenuItem::Forward: + return m_view->canGoForward(); + case ContextMenuItem::Reload: + return true; + case ContextMenuItem::Cut: + return m_contextData.editFlags() & QtWebEngineCore::WebEngineContextMenuData::CanCut; + case ContextMenuItem::Copy: + return m_contextData.editFlags() & QtWebEngineCore::WebEngineContextMenuData::CanCopy; + case ContextMenuItem::Paste: + return m_contextData.editFlags() & QtWebEngineCore::WebEngineContextMenuData::CanPaste; + case ContextMenuItem::Undo: + return m_contextData.editFlags() & QtWebEngineCore::WebEngineContextMenuData::CanUndo; + case ContextMenuItem::Redo: + return m_contextData.editFlags() & QtWebEngineCore::WebEngineContextMenuData::CanRedo; + case ContextMenuItem::SelectAll: + return m_contextData.editFlags() & QtWebEngineCore::WebEngineContextMenuData::CanSelectAll; + case ContextMenuItem::PasteAndMatchStyle: + return m_contextData.editFlags() & QtWebEngineCore::WebEngineContextMenuData::CanPaste; + case ContextMenuItem::OpenLinkInNewWindow: + case ContextMenuItem::OpenLinkInNewTab: + case ContextMenuItem::CopyLinkToClipboard: + case ContextMenuItem::DownloadLinkToDisk: + case ContextMenuItem::CopyImageToClipboard: + case ContextMenuItem::CopyImageUrlToClipboard: + case ContextMenuItem::DownloadImageToDisk: + case ContextMenuItem::CopyMediaUrlToClipboard: + case ContextMenuItem::ToggleMediaControls: + case ContextMenuItem::ToggleMediaLoop: + case ContextMenuItem::DownloadMediaToDisk: + case ContextMenuItem::InspectElement: + case ContextMenuItem::ExitFullScreen: + case ContextMenuItem::SavePage: + return true; + case ContextMenuItem::ViewSource: + return m_view->d_ptr->adapter->canViewSource(); + case ContextMenuItem::SpellingSuggestions: + case ContextMenuItem::Separator: + return true; + } + Q_UNREACHABLE(); +} + QT_END_NAMESPACE diff --git a/src/webengine/api/qquickwebengineview_p.h b/src/webengine/api/qquickwebengineview_p.h index 275503d14..8bda609c0 100644 --- a/src/webengine/api/qquickwebengineview_p.h +++ b/src/webengine/api/qquickwebengineview_p.h @@ -65,6 +65,7 @@ namespace QtWebEngineCore { QT_BEGIN_NAMESPACE class QQmlWebChannel; +class QQuickContextMenuBuilder; class QQuickWebEngineAuthenticationDialogRequest; class QQuickWebEngineCertificateError; class QQuickWebEngineColorDialogRequest; @@ -583,6 +584,7 @@ private: Q_DECLARE_PRIVATE(QQuickWebEngineView) QScopedPointer<QQuickWebEngineViewPrivate> d_ptr; + friend class QQuickContextMenuBuilder; friend class QQuickWebEngineNewViewRequest; friend class QQuickWebEngineFaviconProvider; #ifndef QT_NO_ACCESSIBILITY diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h index baa89718d..cfe99a0d4 100644 --- a/src/webengine/api/qquickwebengineview_p_p.h +++ b/src/webengine/api/qquickwebengineview_p_p.h @@ -52,6 +52,7 @@ // #include "qquickwebengineview_p.h" +#include "render_view_context_menu_qt.h" #include "web_contents_adapter_client.h" #include <QPointer> @@ -215,6 +216,24 @@ private: QQuickWebEngineView *engineView() const { return static_cast<QQuickWebEngineView*>(object()); } }; #endif // QT_NO_ACCESSIBILITY + +class QQuickContextMenuBuilder : public QtWebEngineCore::RenderViewContextMenuQt +{ +public: + QQuickContextMenuBuilder(const QtWebEngineCore::WebEngineContextMenuData &data, QQuickWebEngineView *view, QObject *menu); + void appendExtraItems(QQmlEngine *engine); + +private: + virtual bool hasInspector() override; + virtual bool isFullScreenMode() override; + + virtual void addMenuItem(ContextMenuItem menuItem) override; + virtual bool isMenuItemEnabled(ContextMenuItem menuItem) override; + + QQuickWebEngineView *m_view; + QObject *m_menu; +}; + QT_END_NAMESPACE #endif // QQUICKWEBENGINEVIEW_P_P_H diff --git a/src/webengine/doc/src/webengineview_lgpl.qdoc b/src/webengine/doc/src/webengineview_lgpl.qdoc index fadce39ad..c6985b082 100644 --- a/src/webengine/doc/src/webengineview_lgpl.qdoc +++ b/src/webengine/doc/src/webengineview_lgpl.qdoc @@ -1386,6 +1386,10 @@ will navigate to an internal URL with the developer tools of the view set. + It is recommended to unset this property when developer tools + are not visible; otherwise some debug information may appear + in the inspected WebEngineView. + \sa devToolView */ diff --git a/src/webengine/plugin/plugin.cpp b/src/webengine/plugin/plugin.cpp index 03ce5a332..5f9d16158 100644 --- a/src/webengine/plugin/plugin.cpp +++ b/src/webengine/plugin/plugin.cpp @@ -125,6 +125,8 @@ public: qmlRegisterUncreatableType<QQuickWebEngineContextMenuRequest>(uri, 1, 4, "ContextMenuRequest", msgUncreatableType("ContextMenuRequest")); + qmlRegisterUncreatableType<QQuickWebEngineContextMenuRequest, 1>(uri, 1, 7, "ContextMenuRequest", + msgUncreatableType("ContextMenuRequest")); qmlRegisterUncreatableType<QQuickWebEngineAuthenticationDialogRequest>(uri, 1, 4, "AuthenticationDialogRequest", msgUncreatableType("AuthenticationDialogRequest")); qmlRegisterUncreatableType<QQuickWebEngineJavaScriptDialogRequest>(uri, 1, 4, "JavaScriptDialogRequest", diff --git a/src/webengine/plugin/plugins.qmltypes b/src/webengine/plugin/plugins.qmltypes index b57aa4498..43d7d9064 100644 --- a/src/webengine/plugin/plugins.qmltypes +++ b/src/webengine/plugin/plugins.qmltypes @@ -84,9 +84,12 @@ Module { Component { name: "QQuickWebEngineContextMenuRequest" prototype: "QObject" - exports: ["QtWebEngine/ContextMenuRequest 1.4"] + exports: [ + "QtWebEngine/ContextMenuRequest 1.4", + "QtWebEngine/ContextMenuRequest 1.7" + ] isCreatable: false - exportMetaObjectRevisions: [0] + exportMetaObjectRevisions: [0, 1] Enum { name: "MediaType" values: { @@ -99,6 +102,37 @@ Module { "MediaTypePlugin": 6 } } + Enum { + name: "MediaFlags" + values: { + "MediaNone": 0, + "MediaInError": 1, + "MediaPaused": 2, + "MediaMuted": 4, + "MediaLoop": 8, + "MediaCanSave": 16, + "MediaHasAudio": 32, + "MediaCanToggleControls": 64, + "MediaControls": 128, + "MediaCanPrint": 256, + "MediaCanRotate": 512 + } + } + Enum { + name: "EditFlags" + values: { + "CanDoNone": 0, + "CanUndo": 1, + "CanRedo": 2, + "CanCut": 4, + "CanCopy": 8, + "CanPaste": 16, + "CanDelete": 32, + "CanSelectAll": 64, + "CanTranslate": 128, + "CanEditRichly": 256 + } + } Property { name: "x"; type: "int"; isReadonly: true } Property { name: "y"; type: "int"; isReadonly: true } Property { name: "selectedText"; type: "string"; isReadonly: true } @@ -110,6 +144,8 @@ Module { Property { name: "misspelledWord"; type: "string"; isReadonly: true } Property { name: "spellCheckerSuggestions"; type: "QStringList"; isReadonly: true } Property { name: "accepted"; type: "bool" } + Property { name: "mediaFlags"; revision: 1; type: "MediaFlags"; isReadonly: true } + Property { name: "editFlags"; revision: 1; type: "EditFlags"; isReadonly: true } } Component { name: "QQuickWebEngineDownloadItem" @@ -198,6 +234,7 @@ Module { Property { name: "interruptReasonString"; revision: 4; type: "string"; isReadonly: true } Property { name: "isFinished"; revision: 5; type: "bool"; isReadonly: true } Property { name: "isPaused"; revision: 5; type: "bool"; isReadonly: true } + Property { name: "isSavePageDownload"; revision: 6; type: "bool"; isReadonly: true } Signal { name: "savePageFormatChanged"; revision: 2 } Signal { name: "mimeTypeChanged"; revision: 1 } Signal { name: "typeChanged"; revision: 3 } @@ -527,10 +564,11 @@ Module { "QtWebEngine/WebEngineSettings 1.3", "QtWebEngine/WebEngineSettings 1.4", "QtWebEngine/WebEngineSettings 1.5", - "QtWebEngine/WebEngineSettings 1.6" + "QtWebEngine/WebEngineSettings 1.6", + "QtWebEngine/WebEngineSettings 1.7" ] isCreatable: false - exportMetaObjectRevisions: [0, 1, 2, 3, 4, 5] + exportMetaObjectRevisions: [0, 1, 2, 3, 4, 5, 6] Enum { name: "UnknownUrlSchemePolicy" values: { @@ -565,6 +603,8 @@ Module { Property { name: "allowWindowActivationFromJavaScript"; revision: 5; type: "bool" } Property { name: "showScrollBars"; revision: 5; type: "bool" } Property { name: "unknownUrlSchemePolicy"; revision: 6; type: "UnknownUrlSchemePolicy" } + Property { name: "playbackRequiresUserGesture"; revision: 6; type: "bool" } + Property { name: "webRTCPublicInterfacesOnly"; revision: 6; type: "bool" } Signal { name: "fullScreenSupportEnabledChanged"; revision: 1 } Signal { name: "screenCaptureEnabledChanged"; revision: 2 } Signal { name: "webGLEnabledChanged"; revision: 2 } @@ -578,6 +618,8 @@ Module { Signal { name: "allowWindowActivationFromJavaScriptChanged"; revision: 5 } Signal { name: "showScrollBarsChanged"; revision: 5 } Signal { name: "unknownUrlSchemePolicyChanged"; revision: 6 } + Signal { name: "playbackRequiresUserGestureChanged"; revision: 6 } + Signal { name: "webRTCPublicInterfacesOnlyChanged"; revision: 6 } } Component { name: "QQuickWebEngineSingleton" @@ -606,9 +648,10 @@ Module { "QtWebEngine/WebEngineView 1.3", "QtWebEngine/WebEngineView 1.4", "QtWebEngine/WebEngineView 1.5", - "QtWebEngine/WebEngineView 1.6" + "QtWebEngine/WebEngineView 1.6", + "QtWebEngine/WebEngineView 1.7" ] - exportMetaObjectRevisions: [0, 1, 2, 3, 4, 5, 6] + exportMetaObjectRevisions: [0, 1, 2, 3, 4, 5, 6, 7] Enum { name: "NavigationRequestAction" values: { @@ -921,6 +964,9 @@ Module { Property { name: "audioMuted"; revision: 3; type: "bool" } Property { name: "recentlyAudible"; revision: 3; type: "bool"; isReadonly: true } Property { name: "webChannelWorld"; revision: 3; type: "uint" } + Property { name: "inspectedView"; revision: 7; type: "QQuickWebEngineView"; isPointer: true } + Property { name: "devToolsView"; revision: 7; type: "QQuickWebEngineView"; isPointer: true } + Property { name: "testSupport"; type: "QQuickWebEngineTestSupport"; isPointer: true } Signal { name: "loadingChanged" Parameter { name: "loadRequest"; type: "QQuickWebEngineLoadRequest"; isPointer: true } @@ -1056,6 +1102,14 @@ Module { revision: 7 Parameter { name: "request"; type: "QQuickWebEngineQuotaPermissionRequest" } } + Signal { + name: "geometryChangeRequested" + revision: 7 + Parameter { name: "geometry"; type: "QRect" } + Parameter { name: "frameGeometry"; type: "QRect" } + } + Signal { name: "inspectedViewChanged"; revision: 7 } + Signal { name: "devToolsViewChanged"; revision: 7 } Method { name: "runJavaScript" Parameter { type: "string" } |