summaryrefslogtreecommitdiffstats
path: root/src/webengine
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-02-02 14:22:12 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-02-02 14:22:12 +0100
commitbd605cd2bae8a6c555bb1688573c892831b3ba9d (patch)
tree67beeb63cf353e0dffea0fc6d8cf2bd861877a6b /src/webengine
parentc8bb939e7e45214f17daf8f576582e5bff2527ea (diff)
parent0cc07329495a05fc5f8532c4420bd23db662fdb6 (diff)
Merge remote-tracking branch 'origin/5.11' into dev
Diffstat (limited to 'src/webengine')
-rw-r--r--src/webengine/api/qquickwebenginecontextmenurequest.cpp116
-rw-r--r--src/webengine/api/qquickwebenginecontextmenurequest_p.h38
-rw-r--r--src/webengine/api/qquickwebenginesettings.cpp25
-rw-r--r--src/webengine/api/qquickwebenginesettings_p.h4
-rw-r--r--src/webengine/api/qquickwebengineview.cpp325
-rw-r--r--src/webengine/api/qquickwebengineview_p.h2
-rw-r--r--src/webengine/api/qquickwebengineview_p_p.h19
-rw-r--r--src/webengine/doc/src/webengineview_lgpl.qdoc4
-rw-r--r--src/webengine/plugin/plugin.cpp2
-rw-r--r--src/webengine/plugin/plugins.qmltypes66
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" }