diff options
-rw-r--r-- | src/webengine/api/qquickwebengineaction.cpp | 172 | ||||
-rw-r--r-- | src/webengine/api/qquickwebengineaction_p.h | 108 | ||||
-rw-r--r-- | src/webengine/api/qquickwebengineaction_p_p.h | 86 | ||||
-rw-r--r-- | src/webengine/api/qquickwebengineview.cpp | 282 | ||||
-rw-r--r-- | src/webengine/api/qquickwebengineview_p.h | 2 | ||||
-rw-r--r-- | src/webengine/api/qquickwebengineview_p_p.h | 2 | ||||
-rw-r--r-- | src/webengine/doc/src/webengineview_lgpl.qdoc | 15 | ||||
-rw-r--r-- | src/webengine/plugin/plugin.cpp | 4 | ||||
-rw-r--r-- | src/webengine/plugin/plugins.qmltypes | 38 | ||||
-rw-r--r-- | src/webengine/ui_delegates_manager.cpp | 35 | ||||
-rw-r--r-- | src/webengine/ui_delegates_manager.h | 18 | ||||
-rw-r--r-- | src/webengine/webengine.pro | 3 | ||||
-rw-r--r-- | tests/auto/quick/publicapi/tst_publicapi.cpp | 10 | ||||
-rw-r--r-- | tests/auto/quick/qmltests/data/tst_action.qml | 131 | ||||
-rw-r--r-- | tests/auto/quick/qmltests/data/tst_contextMenu.qml | 5 | ||||
-rw-r--r-- | tests/auto/quick/qmltests/data/tst_viewSource.qml | 9 | ||||
-rw-r--r-- | tests/auto/quick/qmltests/qmltests.pro | 1 |
17 files changed, 828 insertions, 93 deletions
diff --git a/src/webengine/api/qquickwebengineaction.cpp b/src/webengine/api/qquickwebengineaction.cpp new file mode 100644 index 000000000..ce2fe6357 --- /dev/null +++ b/src/webengine/api/qquickwebengineaction.cpp @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qquickwebengineaction_p.h" +#include "qquickwebengineaction_p_p.h" +#include "qquickwebengineview_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \qmltype WebEngineAction + \instantiates QQuickWebEngineAction + \inqmlmodule QtWebEngine + \since QtWebEngine 1.8 + + \brief An action that represents a \l WebEngineView::WebAction + + A WebEngineAction is returned by the \l WebEngineView::action() + method. It provides information about the action, such as + whether it is \l enabled. + + The following code uses the \l WebEngineView::action() method to check if the + the copy action is enabled: + + \code + var copyAction = webEngineView.action(WebEngineView.Copy); + if (copyAction.enabled) + console.log("Copy is enabled."); + else + console.log("Copy is disabled."); + \endcode +*/ + +QQuickWebEngineActionPrivate::QQuickWebEngineActionPrivate(const QVariant &data, const QString &text, const QString &iconText, bool enabled) + : m_data(data) + , m_text(text) + , m_iconText(iconText) + , m_enabled(enabled) +{ +} + +QQuickWebEngineActionPrivate::~QQuickWebEngineActionPrivate() +{ +} + +void QQuickWebEngineActionPrivate::setEnabled(bool enabled) +{ + Q_Q(QQuickWebEngineAction); + if (m_enabled == enabled) + return; + m_enabled = enabled; + emit q->enabledChanged(enabled); +} + +QVariant QQuickWebEngineActionPrivate::data() const +{ + return m_data; +} + +void QQuickWebEngineActionPrivate::trigger() +{ + Q_Q(QQuickWebEngineAction); + if (QQuickWebEngineView *view = static_cast<QQuickWebEngineView*>(q->parent())) { + view->triggerWebAction(static_cast<QQuickWebEngineView::WebAction>(data().toInt())); + } +} + +QQuickWebEngineAction::QQuickWebEngineAction(const QVariant &data, const QString &text, const QString &iconText, bool enabled, QObject *parent) + : QObject(parent) + , d_ptr(new QQuickWebEngineActionPrivate(data, text, iconText, enabled)) +{ + d_ptr->q_ptr = this; +} + +QQuickWebEngineAction::QQuickWebEngineAction(QObject *parent) + : QObject(parent) + , d_ptr(new QQuickWebEngineActionPrivate(-1, QStringLiteral(""), QStringLiteral(""), false)) +{ + d_ptr->q_ptr = this; +} + +QQuickWebEngineAction::~QQuickWebEngineAction() +{ +} + +/*! + \qmlproperty int WebEngineAction::text + + This property holds a textual description of the action. +*/ +QString QQuickWebEngineAction::text() const +{ + Q_D(const QQuickWebEngineAction); + return d->m_text; +} + +/*! + \qmlproperty string WebEngineAction::iconText + + This property holds the action's descriptive icon text +*/ +QString QQuickWebEngineAction::iconText() const +{ + Q_D(const QQuickWebEngineAction); + return d->m_iconText; +} + +/*! + \qmlproperty bool WebEngineAction::enabled + + This property holds whether the action is enabled. +*/ +bool QQuickWebEngineAction::isEnabled() const +{ + Q_D(const QQuickWebEngineAction); + return d->m_enabled; +} + +/*! + \qmlmethod void WebEngineAction::trigger() + + Triggers the action. +*/ +void QQuickWebEngineAction::trigger() +{ + Q_D(QQuickWebEngineAction); + if (!isEnabled()) + return; + + d->trigger(); + emit triggered(); +} + +QT_END_NAMESPACE + diff --git a/src/webengine/api/qquickwebengineaction_p.h b/src/webengine/api/qquickwebengineaction_p.h new file mode 100644 index 000000000..5296f9dd6 --- /dev/null +++ b/src/webengine/api/qquickwebengineaction_p.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKWEBENGINEACTION_P_H +#define QQUICKWEBENGINEACTION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QObject> +#include <QtQml/qqml.h> +#include "qtwebengineglobal_p.h" +#include <QVariant> + +namespace QtWebEngineCore { + class UIDelegatesManager; + class UI2DelegatesManager; +} + +QT_BEGIN_NAMESPACE + +class QQuickWebEngineActionPrivate; + +class Q_WEBENGINE_EXPORT QQuickWebEngineAction : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString text READ text CONSTANT FINAL) + Q_PROPERTY(QString iconText READ iconText CONSTANT FINAL) + Q_PROPERTY(bool enabled READ isEnabled NOTIFY enabledChanged FINAL) + +public: + QQuickWebEngineAction(const QVariant &data, const QString &text, const QString &iconText, bool enabled, QObject *parent); + QQuickWebEngineAction(QObject *parent); + ~QQuickWebEngineAction(); + + QString text() const; + QString iconText() const; + bool isEnabled() const; + +public Q_SLOTS: + Q_INVOKABLE void trigger(); + +Q_SIGNALS: + void toggled(); + void triggered(); + void enabledChanged(const bool enabled); + +private: + Q_DECLARE_PRIVATE(QQuickWebEngineAction) + friend class QQuickWebEngineView; + friend class QQuickWebEngineViewPrivate; + friend class QtWebEngineCore::UIDelegatesManager; + friend class QtWebEngineCore::UI2DelegatesManager; + friend class QQuickContextMenuBuilder; + + QScopedPointer<QQuickWebEngineActionPrivate> d_ptr; +}; + + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickWebEngineAction) + +#endif // QQUICKWEBENGINEACTION_P_H diff --git a/src/webengine/api/qquickwebengineaction_p_p.h b/src/webengine/api/qquickwebengineaction_p_p.h new file mode 100644 index 000000000..cb1817e55 --- /dev/null +++ b/src/webengine/api/qquickwebengineaction_p_p.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKWEBENGINEACTION_P_P_H +#define QQUICKWEBENGINEACTION_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QObject> +#include "qtwebengineglobal_p.h" +#include <QVariant> + +QT_BEGIN_NAMESPACE + +class QQuickWebEngineAction; + +class QQuickWebEngineActionPrivate +{ +public: + Q_DECLARE_PUBLIC(QQuickWebEngineAction) + QQuickWebEngineActionPrivate(const QVariant &data, const QString &text, const QString &iconText, bool enabled); + ~QQuickWebEngineActionPrivate(); + + void setEnabled(bool enabled); + + QVariant data() const; + + void trigger(); + +private: + QQuickWebEngineAction *q_ptr; + + QVariant m_data; + QString m_text; + QString m_iconText; + bool m_enabled; +}; + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINEACTION_P_P_H diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index 9c999e290..aaa8d58c5 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -45,6 +45,9 @@ #include "certificate_error_controller.h" #include "file_picker_controller.h" #include "javascript_dialog_controller.h" + +#include "qquickwebengineaction_p.h" +#include "qquickwebengineaction_p_p.h" #include "qquickwebenginehistory_p.h" #include "qquickwebenginecertificateerror_p.h" #include "qquickwebenginecontextmenurequest_p.h" @@ -126,6 +129,7 @@ QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate() , m_ui2Enabled(false) { m_profile->d_ptr->addWebContentsAdapterClient(this); + memset(actions, 0, sizeof(actions)); QString platform = qApp->platformName().toLower(); if (platform == QLatin1Literal("eglfs")) m_ui2Enabled = true; @@ -803,6 +807,39 @@ void QQuickWebEngineViewPrivate::setFullScreenMode(bool fullscreen) } } +void QQuickWebEngineViewPrivate::updateAction(QQuickWebEngineView::WebAction action) const +{ + QQuickWebEngineAction *a = actions[action]; + if (!a) + return; + + bool enabled = true; + + switch (action) { + case QQuickWebEngineView::Back: + enabled = adapter->canGoBack(); + break; + case QQuickWebEngineView::Forward: + enabled = adapter->canGoForward(); + break; + case QQuickWebEngineView::Stop: + enabled = isLoading; + break; + case QQuickWebEngineView::Reload: + case QQuickWebEngineView::ReloadAndBypassCache: + enabled = !isLoading; + break; + case QQuickWebEngineView::ViewSource: + enabled = adapter->canViewSource(); + break; + default: + break; + } + + a->d_ptr->setEnabled(enabled); +} + + QUrl QQuickWebEngineView::url() const { Q_D(const QQuickWebEngineView); @@ -1650,6 +1687,170 @@ void QQuickWebEngineView::triggerWebAction(WebAction action) } } +QQuickWebEngineAction *QQuickWebEngineView::action(WebAction action) +{ + Q_D(QQuickWebEngineView); + if (action == QQuickWebEngineView::NoWebAction) + return nullptr; + if (d->actions[action]) { + d->updateAction(action); + return d->actions[action]; + } + + QString text; + QString iconText; + + switch (action) { + case Back: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Back); + iconText = QStringLiteral("go-previous"); + break; + case Forward: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Forward); + iconText = QStringLiteral("go-next"); + break; + case Stop: + text = tr("Stop"); + break; + case Reload: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Reload); + iconText = QStringLiteral("view-refresh"); + break; + case ReloadAndBypassCache: + text = tr("Reload and Bypass Cache"); + break; + case Cut: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Cut); + iconText = QStringLiteral("Cut"); + break; + case Copy: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Copy); + break; + case Paste: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Paste); + break; + case Undo: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Undo); + break; + case Redo: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Redo); + break; + case SelectAll: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::SelectAll); + break; + case PasteAndMatchStyle: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::PasteAndMatchStyle); + break; + case OpenLinkInThisWindow: + text = tr("Open link in this window"); + break; + case OpenLinkInNewWindow: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::OpenLinkInNewWindow); + break; + case OpenLinkInNewTab: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::OpenLinkInNewTab); + break; + case CopyLinkToClipboard: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::CopyLinkToClipboard); + break; + case DownloadLinkToDisk: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::DownloadLinkToDisk); + break; + case CopyImageToClipboard: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::CopyImageToClipboard); + break; + case CopyImageUrlToClipboard: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::CopyImageUrlToClipboard); + break; + case DownloadImageToDisk: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::DownloadImageToDisk); + break; + case CopyMediaUrlToClipboard: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::CopyMediaUrlToClipboard); + break; + case ToggleMediaControls: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::ToggleMediaControls); + break; + case ToggleMediaLoop: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::ToggleMediaLoop); + break; + case ToggleMediaPlayPause: + text = tr("Toggle Play/Pause"); + break; + case ToggleMediaMute: + text = tr("Toggle Mute"); + break; + case DownloadMediaToDisk: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::DownloadMediaToDisk); + break; + case InspectElement: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::InspectElement); + break; + case ExitFullScreen: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::ExitFullScreen); + break; + case RequestClose: + text = tr("Close Page"); + break; + case Unselect: + text = tr("Unselect"); + break; + case SavePage: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::SavePage); + break; + case ViewSource: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::ViewSource); + iconText = QStringLiteral("view-source"); + break; + case ToggleBold: + text = tr("&Bold"); + break; + case ToggleItalic: + text = tr("&Italic"); + break; + case ToggleUnderline: + text = tr("&Underline"); + break; + case ToggleStrikethrough: + text = tr("&Strikethrough"); + break; + case AlignLeft: + text = tr("Align &Left"); + break; + case AlignCenter: + text = tr("Align &Center"); + break; + case AlignRight: + text = tr("Align &Right"); + break; + case AlignJustified: + text = tr("Align &Justified"); + break; + case Indent: + text = tr("&Indent"); + break; + case Outdent: + text = tr("&Outdent"); + break; + case InsertOrderedList: + text = tr("Insert &Ordered List"); + break; + case InsertUnorderedList: + text = tr("Insert &Unordered List"); + break; + case NoWebAction: + case WebActionCount: + Q_UNREACHABLE(); + break; + } + + QQuickWebEngineAction *retVal = new QQuickWebEngineAction(action, text, iconText, false, this); + + d->actions[action] = retVal; + d->updateAction(action); + return retVal; +} + QSizeF QQuickWebEngineView::contentsSize() const { Q_D(const QQuickWebEngineView); @@ -1778,112 +1979,101 @@ bool QQuickContextMenuBuilder::isFullScreenMode() void QQuickContextMenuBuilder::addMenuItem(ContextMenuItem menuItem) { - MenuItemHandler *item = new MenuItemHandler(m_menu); - QString menuItemIcon; - QPointer<QQuickWebEngineView> thisRef(m_view); + QQuickWebEngineAction *action = nullptr; switch (menuItem) { case ContextMenuItem::Back: - QObject::connect(item, &MenuItemHandler::triggered, thisRef, &QQuickWebEngineView::goBack); - menuItemIcon = QStringLiteral("go-previous"); + action = m_view->action(QQuickWebEngineView::Back); break; case ContextMenuItem::Forward: - QObject::connect(item, &MenuItemHandler::triggered, thisRef, &QQuickWebEngineView::goForward); - menuItemIcon = QStringLiteral("go-next"); + action = m_view->action(QQuickWebEngineView::Forward); break; case ContextMenuItem::Reload: - QObject::connect(item, &MenuItemHandler::triggered, thisRef, &QQuickWebEngineView::reload); - menuItemIcon = QStringLiteral("view-refresh"); + action = m_view->action(QQuickWebEngineView::Reload); break; case ContextMenuItem::Cut: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::Cut); }); - menuItemIcon = QStringLiteral("Cut"); + action = m_view->action(QQuickWebEngineView::Cut); break; case ContextMenuItem::Copy: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::Copy); }); - menuItemIcon = QStringLiteral("Copy"); + action = m_view->action(QQuickWebEngineView::Copy); break; - case ContextMenuItem::Paste: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::Paste); }); - menuItemIcon = QStringLiteral("Paste"); + action = m_view->action(QQuickWebEngineView::Paste); break; case ContextMenuItem::Undo: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::Undo); }); - menuItemIcon = QStringLiteral("Undo"); + action = m_view->action(QQuickWebEngineView::Undo); break; case ContextMenuItem::Redo: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::Redo); }); - menuItemIcon = QStringLiteral("Redo"); + action = m_view->action(QQuickWebEngineView::Redo); break; case ContextMenuItem::SelectAll: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::SelectAll); }); - menuItemIcon = QStringLiteral("Select All"); + action = m_view->action(QQuickWebEngineView::SelectAll); break; case ContextMenuItem::PasteAndMatchStyle: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::PasteAndMatchStyle); }); - menuItemIcon = QStringLiteral("Paste And Match Style"); + action = m_view->action(QQuickWebEngineView::PasteAndMatchStyle); break; case ContextMenuItem::OpenLinkInNewWindow: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::OpenLinkInNewWindow); }); + action = m_view->action(QQuickWebEngineView::OpenLinkInNewWindow); break; case ContextMenuItem::OpenLinkInNewTab: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::OpenLinkInNewTab); }); + action = m_view->action(QQuickWebEngineView::OpenLinkInNewTab); break; case ContextMenuItem::CopyLinkToClipboard: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::CopyLinkToClipboard); }); + action = m_view->action(QQuickWebEngineView::CopyLinkToClipboard); break; case ContextMenuItem::DownloadLinkToDisk: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::DownloadLinkToDisk); }); + action = m_view->action(QQuickWebEngineView::DownloadLinkToDisk); break; case ContextMenuItem::CopyImageToClipboard: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::CopyImageToClipboard); }); + action = m_view->action(QQuickWebEngineView::CopyImageToClipboard); break; case ContextMenuItem::CopyImageUrlToClipboard: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::CopyImageUrlToClipboard); }); + action = m_view->action(QQuickWebEngineView::CopyImageUrlToClipboard); break; case ContextMenuItem::DownloadImageToDisk: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::DownloadImageToDisk); }); + action = m_view->action(QQuickWebEngineView::DownloadImageToDisk); break; case ContextMenuItem::CopyMediaUrlToClipboard: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::CopyMediaUrlToClipboard); }); + action = m_view->action(QQuickWebEngineView::CopyMediaUrlToClipboard); break; case ContextMenuItem::ToggleMediaControls: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::ToggleMediaControls); }); + action = m_view->action(QQuickWebEngineView::ToggleMediaControls); break; case ContextMenuItem::ToggleMediaLoop: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::ToggleMediaLoop); }); + action = m_view->action(QQuickWebEngineView::ToggleMediaLoop); break; case ContextMenuItem::DownloadMediaToDisk: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::DownloadMediaToDisk); }); + action = m_view->action(QQuickWebEngineView::DownloadMediaToDisk); break; case ContextMenuItem::InspectElement: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::InspectElement); }); + action = m_view->action(QQuickWebEngineView::InspectElement); break; case ContextMenuItem::ExitFullScreen: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::ExitFullScreen); }); + action = m_view->action(QQuickWebEngineView::ExitFullScreen); break; case ContextMenuItem::SavePage: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::SavePage); }); + action = m_view->action(QQuickWebEngineView::SavePage); break; case ContextMenuItem::ViewSource: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::ViewSource); }); - menuItemIcon = QStringLiteral("view-source"); + action = m_view->action(QQuickWebEngineView::ViewSource); break; case ContextMenuItem::SpellingSuggestions: + { + QPointer<QQuickWebEngineView> thisRef(m_view); for (int i=0; i < m_contextData.spellCheckerSuggestions().count() && i < 4; i++) { - item = new MenuItemHandler(m_menu); + action = new QQuickWebEngineAction(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); + QObject::connect(action, &QQuickWebEngineAction::triggered, [thisRef, replacement] { thisRef->replaceMisspelledWord(replacement); }); + m_view->d_ptr->ui()->addMenuItem(action, m_menu); } return; + } case ContextMenuItem::Separator: - thisRef->d_ptr->ui()->addMenuSeparator(m_menu); + m_view->d_ptr->ui()->addMenuSeparator(m_menu); return; } - QString menuItemName = RenderViewContextMenuQt::getMenuItemName(menuItem); - thisRef->d_ptr->ui()->addMenuItem(item, menuItemName, menuItemIcon, isMenuItemEnabled(menuItem)); + action->d_ptr->setEnabled(isMenuItemEnabled(menuItem)); + m_view->d_ptr->ui()->addMenuItem(action, m_menu); } bool QQuickContextMenuBuilder::isMenuItemEnabled(ContextMenuItem menuItem) diff --git a/src/webengine/api/qquickwebengineview_p.h b/src/webengine/api/qquickwebengineview_p.h index 0ca0c7886..d400fc75e 100644 --- a/src/webengine/api/qquickwebengineview_p.h +++ b/src/webengine/api/qquickwebengineview_p.h @@ -62,6 +62,7 @@ QT_BEGIN_NAMESPACE class QQmlWebChannel; class QQuickContextMenuBuilder; +class QQuickWebEngineAction; class QQuickWebEngineAuthenticationDialogRequest; class QQuickWebEngineCertificateError; class QQuickWebEngineColorDialogRequest; @@ -470,6 +471,7 @@ public: QQuickWebEngineHistory *navigationHistory() const; uint webChannelWorld() const; void setWebChannelWorld(uint); + Q_REVISION(8) Q_INVOKABLE QQuickWebEngineAction *action(WebAction action); bool isAudioMuted() const; void setAudioMuted(bool muted); diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h index 062125e70..7f52c7216 100644 --- a/src/webengine/api/qquickwebengineview_p_p.h +++ b/src/webengine/api/qquickwebengineview_p_p.h @@ -155,6 +155,7 @@ public: QtWebEngineCore::ProfileAdapter *profileAdapter() override; QtWebEngineCore::WebContentsAdapter *webContentsAdapter() override; + void updateAction(QQuickWebEngineView::WebAction) const; void adoptWebContents(QtWebEngineCore::WebContentsAdapter *webContents); void setProfile(QQuickWebEngineProfile *profile); void ensureContentsAdapter(); @@ -191,6 +192,7 @@ public: QPointer<QQuickWebEngineView> devToolsView; uint m_webChannelWorld; bool m_isBeingAdopted; + mutable QQuickWebEngineAction *actions[QQuickWebEngineView::WebActionCount]; private: QScopedPointer<QtWebEngineCore::UIDelegatesManager> m_uIDelegatesManager; diff --git a/src/webengine/doc/src/webengineview_lgpl.qdoc b/src/webengine/doc/src/webengineview_lgpl.qdoc index a6a7c088b..741dee2f7 100644 --- a/src/webengine/doc/src/webengineview_lgpl.qdoc +++ b/src/webengine/doc/src/webengineview_lgpl.qdoc @@ -1447,3 +1447,18 @@ \sa inspectedView */ + +/*! + \qmlmethod WebEngineAction WebEngineView::action(WebAction action) + \since 5.12 + + Returns a \l WebEngineAction for the specified \l WebAction action. + WebEngineView also takes care of implementing the action, + so that upon triggering the corresponding action is performed on the view. + + \code + var copyAction = webEngineView.action(WebEngineView.Copy); + \endcode + + \sa WebEngineAction +*/ diff --git a/src/webengine/plugin/plugin.cpp b/src/webengine/plugin/plugin.cpp index 545f17f82..76bee50be 100644 --- a/src/webengine/plugin/plugin.cpp +++ b/src/webengine/plugin/plugin.cpp @@ -52,6 +52,7 @@ #include "qquickwebenginesettings_p.h" #include "qquickwebenginesingleton_p.h" #include "qquickwebengineview_p.h" +#include "qquickwebengineaction_p.h" #include "qwebenginequotarequest.h" #include "qwebengineregisterprotocolhandlerrequest.h" #include "qtwebengineversion.h" @@ -89,6 +90,7 @@ public: qmlRegisterType<QQuickWebEngineView, 5>(uri, 1, 5, "WebEngineView"); qmlRegisterType<QQuickWebEngineView, 6>(uri, 1, 6, "WebEngineView"); qmlRegisterType<QQuickWebEngineView, 7>(uri, 1, 7, "WebEngineView"); + qmlRegisterType<QQuickWebEngineView, 8>(uri, 1, 8, "WebEngineView"); qmlRegisterType<QQuickWebEngineProfile>(uri, 1, 1, "WebEngineProfile"); qmlRegisterType<QQuickWebEngineProfile, 1>(uri, 1, 2, "WebEngineProfile"); qmlRegisterType<QQuickWebEngineProfile, 2>(uri, 1, 3, "WebEngineProfile"); @@ -148,7 +150,7 @@ public: qRegisterMetaType<QWebEngineRegisterProtocolHandlerRequest>(); qmlRegisterUncreatableType<QWebEngineRegisterProtocolHandlerRequest>(uri, 1, 7, "RegisterProtocolHandlerRequest", msgUncreatableType("RegisterProtocolHandlerRequest")); - + qmlRegisterUncreatableType<QQuickWebEngineAction>(uri, 1, 8, "WebEngineAction", msgUncreatableType("WebEngineAction")); } private: diff --git a/src/webengine/plugin/plugins.qmltypes b/src/webengine/plugin/plugins.qmltypes index 5c61ee8d0..44c85bd8e 100644 --- a/src/webengine/plugin/plugins.qmltypes +++ b/src/webengine/plugin/plugins.qmltypes @@ -4,11 +4,36 @@ import QtQuick.tooling 1.2 // It is used for QML tooling purposes only. // // This file was auto-generated by: -// 'qmlplugindump -defaultplatform -dependencies dependencies.json -nonrelocatable QtWebEngine 1.7' +// 'qmlplugindump -defaultplatform -dependencies dependencies.json -nonrelocatable QtWebEngine 1.8' Module { dependencies: ["QtQuick 2.8"] Component { + name: "QQuickWebEngineAction" + prototype: "QObject" + exports: ["QtWebEngine/WebEngineAction 1.8"] + isCreatable: false + exportMetaObjectRevisions: [0] + Property { name: "text"; type: "string"; isReadonly: true } + Property { name: "iconText"; type: "string"; isReadonly: true } + Property { name: "enabled"; type: "bool"; isReadonly: true } + Signal { name: "toggled" } + Signal { name: "triggered" } + Signal { + name: "textChanged" + Parameter { name: "text"; type: "string" } + } + Signal { + name: "iconTextChanged" + Parameter { name: "iconText"; type: "string" } + } + Signal { + name: "enabledChanged" + Parameter { name: "enabled"; type: "bool" } + } + Method { name: "trigger" } + } + Component { name: "QQuickWebEngineAuthenticationDialogRequest" prototype: "QObject" exports: ["QtWebEngine/AuthenticationDialogRequest 1.4"] @@ -640,9 +665,10 @@ Module { "QtWebEngine/WebEngineView 1.4", "QtWebEngine/WebEngineView 1.5", "QtWebEngine/WebEngineView 1.6", - "QtWebEngine/WebEngineView 1.7" + "QtWebEngine/WebEngineView 1.7", + "QtWebEngine/WebEngineView 1.8" ] - exportMetaObjectRevisions: [0, 1, 2, 3, 4, 5, 6, 7] + exportMetaObjectRevisions: [0, 1, 2, 3, 4, 5, 6, 7, 8] Enum { name: "NavigationRequestAction" values: { @@ -1224,6 +1250,12 @@ Module { revision: 4 Parameter { name: "replacement"; type: "string" } } + Method { + name: "action" + revision: 8 + type: "QQuickWebEngineAction*" + Parameter { name: "action"; type: "WebAction" } + } } Component { name: "QWebEngineQuotaRequest" diff --git a/src/webengine/ui_delegates_manager.cpp b/src/webengine/ui_delegates_manager.cpp index 4570172d7..c35d26017 100644 --- a/src/webengine/ui_delegates_manager.cpp +++ b/src/webengine/ui_delegates_manager.cpp @@ -119,11 +119,6 @@ const char *defaultPropertyName(QObject *obj) return info.value(); } -MenuItemHandler::MenuItemHandler(QObject *parent) - : QObject(parent) -{ -} - #define COMPONENT_MEMBER_INIT(TYPE, COMPONENT) \ , COMPONENT##Component(0) @@ -212,26 +207,25 @@ bool UIDelegatesManager::ensureComponentLoaded(ComponentType type) if (!prop.isSignalProperty()) \ qWarning("%s is missing %s signal property.\n", qPrintable(location.toString()), qPrintable(prop.name())); -void UIDelegatesManager::addMenuItem(MenuItemHandler *menuItemHandler, const QString &text, const QString &iconName, bool enabled, - bool checkable, bool checked) +void UIDelegatesManager::addMenuItem(QQuickWebEngineAction *action, QObject *menu, bool checkable, bool checked) { - Q_ASSERT(menuItemHandler); + Q_ASSERT(action); if (!ensureComponentLoaded(MenuItem)) return; QObject *it = menuItemComponent->beginCreate(qmlContext(m_view)); - QQmlProperty(it, QStringLiteral("text")).write(text); - QQmlProperty(it, QStringLiteral("iconName")).write(iconName); - QQmlProperty(it, QStringLiteral("enabled")).write(enabled); + QQmlProperty(it, QStringLiteral("text")).write(action->text()); + QQmlProperty(it, QStringLiteral("iconName")).write(action->iconText()); + QQmlProperty(it, QStringLiteral("enabled")).write(action->isEnabled()); QQmlProperty(it, QStringLiteral("checkable")).write(checkable); QQmlProperty(it, QStringLiteral("checked")).write(checked); QQmlProperty signal(it, QStringLiteral("onTriggered")); CHECK_QML_SIGNAL_PROPERTY(signal, menuItemComponent->url()); - QObject::connect(it, signal.method(), menuItemHandler, QMetaMethod::fromSignal(&MenuItemHandler::triggered)); + const QMetaObject *actionMeta = action->metaObject(); + QObject::connect(it, signal.method(), action, actionMeta->method(actionMeta->indexOfSlot("trigger()"))); menuItemComponent->completeCreate(); - QObject *menu = menuItemHandler->parent(); it->setParent(menu); QQmlListReference entries(menu, defaultPropertyName(menu), qmlEngine(m_view)); @@ -636,28 +630,25 @@ QObject *UI2DelegatesManager::addMenu(QObject *parentMenu, const QString &title, return menu; } -void UI2DelegatesManager::addMenuItem(MenuItemHandler *menuItemHandler, const QString &text, - const QString &/*iconName*/, bool enabled, - bool checkable, bool checked) +void UI2DelegatesManager::addMenuItem(QQuickWebEngineAction *action, QObject *menu, bool checkable, bool checked) { - Q_ASSERT(menuItemHandler); + Q_ASSERT(action); if (!ensureComponentLoaded(MenuItem)) return; QObject *it = menuItemComponent->beginCreate(qmlContext(m_view)); - it->setProperty("text", text); - it->setProperty("enabled", enabled); + it->setProperty("text", action->text()); + it->setProperty("enabled", action->isEnabled()); it->setProperty("checked", checked); it->setProperty("checkable", checkable); QQmlProperty signal(it, QStringLiteral("onTriggered")); CHECK_QML_SIGNAL_PROPERTY(signal, menuItemComponent->url()); - QObject::connect(it, signal.method(), menuItemHandler, - QMetaMethod::fromSignal(&MenuItemHandler::triggered)); + const QMetaObject *actionMeta = action->metaObject(); + QObject::connect(it, signal.method(), action, actionMeta->method(actionMeta->indexOfSlot("trigger()"))); menuItemComponent->completeCreate(); - QObject *menu = menuItemHandler->parent(); it->setParent(menu); QQmlListReference entries(menu, defaultPropertyName(menu), qmlEngine(m_view)); diff --git a/src/webengine/ui_delegates_manager.h b/src/webengine/ui_delegates_manager.h index 1cbf2ad28..18457e4ed 100644 --- a/src/webengine/ui_delegates_manager.h +++ b/src/webengine/ui_delegates_manager.h @@ -40,6 +40,7 @@ #ifndef UI_DELEGATES_MANAGER_H #define UI_DELEGATES_MANAGER_H +#include "api/qquickwebengineaction_p.h" #include "qglobal.h" #include "web_contents_adapter.h" #include "web_contents_adapter_client.h" @@ -83,15 +84,6 @@ class FilePickerController; const char *defaultPropertyName(QObject *obj); -class MenuItemHandler : public QObject { -Q_OBJECT -public: - MenuItemHandler(QObject *parent); - -Q_SIGNALS: - void triggered(); -}; - class UIDelegatesManager { Q_DECLARE_TR_FUNCTIONS(UIDelegatesManager) @@ -106,9 +98,7 @@ public: virtual ~UIDelegatesManager(); virtual bool initializeImportDirs(QStringList &dirs, QQmlEngine *engine); - virtual void addMenuItem(MenuItemHandler *menuItemHandler, const QString &text, - const QString &iconName = QString(), - bool enabled = true, + virtual void addMenuItem(QQuickWebEngineAction *action, QObject *menu, bool checkable = false, bool checked = true); void addMenuSeparator(QObject *menu); virtual QObject *addMenu(QObject *parentMenu, const QString &title, @@ -143,9 +133,7 @@ public: bool initializeImportDirs(QStringList &dirs, QQmlEngine *engine) override; QObject *addMenu(QObject *parentMenu, const QString &title, const QPoint &pos = QPoint()) override; - void addMenuItem(MenuItemHandler *menuItemHandler, const QString &text, - const QString &iconName = QString(), - bool enabled = true, + void addMenuItem(QQuickWebEngineAction *action, QObject *menu, bool checkable = false, bool checked = false) override; void showMenu(QObject *menu) override; Q_DISABLE_COPY(UI2DelegatesManager) diff --git a/src/webengine/webengine.pro b/src/webengine/webengine.pro index 7b2818a06..418ade9a8 100644 --- a/src/webengine/webengine.pro +++ b/src/webengine/webengine.pro @@ -14,6 +14,7 @@ QMAKE_DOCS = $$PWD/doc/qtwebengine.qdocconf INCLUDEPATH += $$PWD api ../core ../core/api SOURCES = \ + api/qquickwebengineaction.cpp \ api/qquickwebenginecertificateerror.cpp \ api/qquickwebenginecontextmenurequest.cpp \ api/qquickwebenginedialogrequests.cpp \ @@ -36,6 +37,8 @@ SOURCES = \ HEADERS = \ api/qtwebengineglobal.h \ api/qtwebengineglobal_p.h \ + api/qquickwebengineaction_p.h \ + api/qquickwebengineaction_p_p.h \ api/qquickwebenginecertificateerror_p.h \ api/qquickwebenginecontextmenurequest_p.h \ api/qquickwebenginedialogrequests_p.h \ diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp index aa65509c3..d8c1bd80c 100644 --- a/tests/auto/quick/publicapi/tst_publicapi.cpp +++ b/tests/auto/quick/publicapi/tst_publicapi.cpp @@ -38,6 +38,7 @@ #include <QtWebEngineCore/QWebEngineQuotaRequest> #include <QtWebEngineCore/QWebEngineRegisterProtocolHandlerRequest> #include <private/qquickwebengineview_p.h> +#include <private/qquickwebengineaction_p.h> #include <private/qquickwebenginecertificateerror_p.h> #include <private/qquickwebenginedialogrequests_p.h> #include <private/qquickwebenginedownloaditem_p.h> @@ -57,6 +58,7 @@ private Q_SLOTS: static const QList<const QMetaObject *> typesToCheck = QList<const QMetaObject *>() << &QQuickWebEngineView::staticMetaObject + << &QQuickWebEngineAction::staticMetaObject << &QQuickWebEngineCertificateError::staticMetaObject << &QQuickWebEngineDownloadItem::staticMetaObject << &QQuickWebEngineHistory::staticMetaObject @@ -93,6 +95,13 @@ static const QStringList hardcodedTypes = QStringList() ; static const QStringList expectedAPI = QStringList() + << "QQuickWebEngineAction.text --> QString" + << "QQuickWebEngineAction.iconText --> QString" + << "QQuickWebEngineAction.enabled --> bool" + << "QQuickWebEngineAction.toggled() --> void" + << "QQuickWebEngineAction.triggered() --> void" + << "QQuickWebEngineAction.enabledChanged(bool) --> void" + << "QQuickWebEngineAction.trigger() --> void" << "QQuickWebEngineAuthenticationDialogRequest.AuthenticationTypeHTTP --> AuthenticationType" << "QQuickWebEngineAuthenticationDialogRequest.AuthenticationTypeProxy --> AuthenticationType" << "QQuickWebEngineAuthenticationDialogRequest.accepted --> bool" @@ -380,6 +389,7 @@ static const QStringList expectedAPI = QStringList() << "QQuickWebEngineSettings.webRTCPublicInterfacesOnlyChanged() --> void" << "QQuickWebEngineSingleton.defaultProfile --> QQuickWebEngineProfile*" << "QQuickWebEngineSingleton.settings --> QQuickWebEngineSettings*" + << "QQuickWebEngineView.action(WebAction) --> QQuickWebEngineAction*" << "QQuickWebEngineView.A0 --> PrintedPageSizeId" << "QQuickWebEngineView.A1 --> PrintedPageSizeId" << "QQuickWebEngineView.A10 --> PrintedPageSizeId" diff --git a/tests/auto/quick/qmltests/data/tst_action.qml b/tests/auto/quick/qmltests/data/tst_action.qml new file mode 100644 index 000000000..b27e7d821 --- /dev/null +++ b/tests/auto/quick/qmltests/data/tst_action.qml @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.2 +import QtTest 1.0 +import QtWebEngine 1.8 + +TestWebEngineView { + id: webEngineView + width: 400 + height: 400 + + Component { + id: signalSpy + SignalSpy { } + } + + TestCase { + id: actionTests + name: "WebEngineAction" + when: windowShown + + function test_actions_data() { + return [ + { webAction: WebEngineView.Back, text: "Back", iconText: "go-previous", enabled: false }, + { webAction: WebEngineView.Forward, text: "Forward", iconText: "go-next", enabled: false }, + { webAction: WebEngineView.Stop, text: "Stop", iconText: "", enabled: false }, + { webAction: WebEngineView.Reload, text: "Reload", iconText: "view-refresh", enabled: true }, + { webAction: WebEngineView.Cut, text: "Cut", iconText: "Cut", enabled: true }, + { webAction: WebEngineView.Copy, text: "Copy", iconText: "", enabled: true }, + { webAction: WebEngineView.Paste, text: "Paste", iconText: "", enabled: true }, + { webAction: WebEngineView.Undo, text: "Undo", iconText: "", enabled: true }, + { webAction: WebEngineView.Redo, text: "Redo", iconText: "", enabled: true }, + { webAction: WebEngineView.SelectAll, text: "Select all", iconText: "", enabled: true }, + { webAction: WebEngineView.ReloadAndBypassCache, text: "Reload and Bypass Cache", iconText: "", enabled: true }, + { webAction: WebEngineView.PasteAndMatchStyle, text: "Paste and match style", iconText: "", enabled: true }, + { webAction: WebEngineView.OpenLinkInThisWindow, text: "Open link in this window", iconText: "", enabled: true }, + { webAction: WebEngineView.OpenLinkInNewWindow, text: "Open link in new window", iconText: "", enabled: true }, + { webAction: WebEngineView.OpenLinkInNewTab, text: "Open link in new tab", iconText: "", enabled: true }, + { webAction: WebEngineView.CopyLinkToClipboard, text: "Copy link address", iconText: "", enabled: true }, + { webAction: WebEngineView.DownloadLinkToDisk, text: "Save link", iconText: "", enabled: true }, + { webAction: WebEngineView.CopyImageToClipboard, text: "Copy image", iconText: "", enabled: true }, + { webAction: WebEngineView.CopyImageUrlToClipboard, text: "Copy image address", iconText: "", enabled: true }, + { webAction: WebEngineView.DownloadImageToDisk, text: "Save image", iconText: "", enabled: true }, + { webAction: WebEngineView.CopyMediaUrlToClipboard, text: "Copy media address", iconText: "", enabled: true }, + { webAction: WebEngineView.ToggleMediaControls, text: "Show controls", iconText: "", enabled: true }, + { webAction: WebEngineView.ToggleMediaLoop, text: "Loop", iconText: "", enabled: true }, + { webAction: WebEngineView.ToggleMediaPlayPause, text: "Toggle Play/Pause", iconText: "", enabled: true }, + { webAction: WebEngineView.ToggleMediaMute, text: "Toggle Mute", iconText: "", enabled: true }, + { webAction: WebEngineView.DownloadMediaToDisk, text: "Save media", iconText: "", enabled: true }, + { webAction: WebEngineView.InspectElement, text: "Inspect", iconText: "", enabled: true }, + { webAction: WebEngineView.ExitFullScreen, text: "Exit full screen", iconText: "", enabled: true }, + { webAction: WebEngineView.RequestClose, text: "Close Page", iconText: "", enabled: true }, + { webAction: WebEngineView.Unselect, text: "Unselect", iconText: "", enabled: true }, + { webAction: WebEngineView.SavePage, text: "Save page", iconText: "", enabled: true }, + { webAction: WebEngineView.ViewSource, text: "View page source", iconText: "view-source", enabled: true }, + { webAction: WebEngineView.ToggleBold, text: "&Bold", iconText: "", enabled: true }, + { webAction: WebEngineView.ToggleItalic, text: "&Italic", iconText: "", enabled: true }, + { webAction: WebEngineView.ToggleUnderline, text: "&Underline", iconText: "", enabled: true }, + { webAction: WebEngineView.ToggleStrikethrough, text: "&Strikethrough", iconText: "", enabled: true }, + { webAction: WebEngineView.AlignLeft, text: "Align &Left", iconText: "", enabled: true }, + { webAction: WebEngineView.AlignCenter, text: "Align &Center", iconText: "", enabled: true }, + { webAction: WebEngineView.AlignRight, text: "Align &Right", iconText: "", enabled: true }, + { webAction: WebEngineView.AlignJustified, text: "Align &Justified", iconText: "", enabled: true }, + { webAction: WebEngineView.Indent, text: "&Indent", iconText: "", enabled: true }, + { webAction: WebEngineView.Outdent, text: "&Outdent", iconText: "", enabled: true }, + { webAction: WebEngineView.InsertOrderedList, text: "Insert &Ordered List", iconText: "", enabled: true }, + { webAction: WebEngineView.InsertUnorderedList, text: "Insert &Unordered List", iconText: "", enabled: true } + ]; + } + + function test_actions(row) { + webEngineView.url = Qt.resolvedUrl("test1.html"); + verify(webEngineView.waitForLoadSucceeded()); + + var action = webEngineView.action(row.webAction); + verify(action); + + compare(action.text, row.text); + compare(action.iconText, row.iconText); + compare(action.enabled, row.enabled); + } + + function test_trigger() { + webEngineView.url = Qt.resolvedUrl("test1.html"); + verify(webEngineView.waitForLoadSucceeded()); + + var copyAction = webEngineView.action(WebEngineView.Copy); + verify(copyAction); + + var stopAction = webEngineView.action(WebEngineView.Stop); + verify(stopAction); + + var triggerSpy = createTemporaryObject(signalSpy, actionTests, {target: copyAction, signalName: "triggered"}); + var stopTriggerSpy = createTemporaryObject(signalSpy, actionTests, {target: stopAction, signalName: "triggered"}); + + verify(copyAction.enabled); + copyAction.trigger(); + compare(triggerSpy.count, 1); + + verify(!stopAction.enabled); + stopAction.trigger(); + compare(stopTriggerSpy.count, 0); + } + } +} diff --git a/tests/auto/quick/qmltests/data/tst_contextMenu.qml b/tests/auto/quick/qmltests/data/tst_contextMenu.qml index 4b6ba2bee..99450a159 100644 --- a/tests/auto/quick/qmltests/data/tst_contextMenu.qml +++ b/tests/auto/quick/qmltests/data/tst_contextMenu.qml @@ -144,6 +144,11 @@ TestWebEngineView { compare(mediaType, ContextMenuRequest.MediaTypeNone); compare(selectedText, ""); + verify(webEngineView.action(WebEngineView.OpenLinkInNewTab).enabled); + verify(webEngineView.action(WebEngineView.OpenLinkInNewWindow).enabled); + verify(webEngineView.action(WebEngineView.DownloadLinkToDisk).enabled); + verify(webEngineView.action(WebEngineView.CopyLinkToClipboard).enabled); + contextMenuRequestedSpy.clear(); // FIXME: Sometimes the keyPress(Qt.Key_Escape) event isn't caught so we keep trying tryVerify(destroyContextMenu); diff --git a/tests/auto/quick/qmltests/data/tst_viewSource.qml b/tests/auto/quick/qmltests/data/tst_viewSource.qml index b21d72eb2..4966a052a 100644 --- a/tests/auto/quick/qmltests/data/tst_viewSource.qml +++ b/tests/auto/quick/qmltests/data/tst_viewSource.qml @@ -77,8 +77,7 @@ TestWebEngineView { webEngineView.url = Qt.resolvedUrl("test1.html"); verify(webEngineView.waitForLoadSucceeded()); tryCompare(webEngineView, "title", "Test page 1"); - // FIXME(pvarga): Reintroduce this check in the fix for QTBUG-56117 - //verify(webEngineView.canViewSource, true); + verify(webEngineView.action(WebEngineView.ViewSource).enabled); titleChangedSpy.clear(); webEngineView.triggerWebAction(WebEngineView.ViewSource); @@ -89,8 +88,7 @@ TestWebEngineView { compare(viewRequest.destination, WebEngineView.NewViewInTab); verify(viewRequest.userInitiated); - // FIXME(pvarga): Reintroduce this check in the fix for QTBUG-56117 - //verify(!webEngineView.canViewSource); + verify(!webEngineView.action(WebEngineView.ViewSource).enabled); tryCompare(webEngineView, "title", "test1.html"); compare(webEngineView.url, "view-source:" + Qt.resolvedUrl("test1.html")); @@ -123,8 +121,7 @@ TestWebEngineView { compare(webEngineView.url, row.url); tryCompare(webEngineView, "title", row.title); - // FIXME(pvarga): Reintroduce this check in the fix for QTBUG-56117 - //verify(!webEngineView.canViewSource); + verify(!webEngineView.action(WebEngineView.ViewSource).enabled); } function test_viewSourceCredentials() { diff --git a/tests/auto/quick/qmltests/qmltests.pro b/tests/auto/quick/qmltests/qmltests.pro index 5395da0b5..a2b05e091 100644 --- a/tests/auto/quick/qmltests/qmltests.pro +++ b/tests/auto/quick/qmltests/qmltests.pro @@ -42,6 +42,7 @@ OTHER_FILES += \ $$PWD/data/keyboardModifierMapping.html \ $$PWD/data/keyboardEvents.html \ $$PWD/data/titleupdate.js \ + $$PWD/data/tst_action.qml \ $$PWD/data/tst_activeFocusOnPress.qml \ $$PWD/data/tst_contextMenu.qml \ $$PWD/data/tst_desktopBehaviorLoadHtml.qml \ |