diff options
Diffstat (limited to 'src/webengine')
-rw-r--r-- | src/webengine/api/qquickwebengineview.cpp | 89 | ||||
-rw-r--r-- | src/webengine/api/qquickwebengineview_p_p.h | 16 | ||||
-rw-r--r-- | src/webengine/ui/Menu.qml | 50 | ||||
-rw-r--r-- | src/webengine/ui/MenuItem.qml | 46 | ||||
-rw-r--r-- | src/webengine/ui/MenuSeparator.qml | 45 | ||||
-rw-r--r-- | src/webengine/ui/qmldir | 4 | ||||
-rw-r--r-- | src/webengine/ui/ui.pro | 8 | ||||
-rw-r--r-- | src/webengine/ui_delegates_manager.cpp | 233 | ||||
-rw-r--r-- | src/webengine/ui_delegates_manager.h | 130 | ||||
-rw-r--r-- | src/webengine/webengine.pro | 6 |
10 files changed, 622 insertions, 5 deletions
diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index ac2dc681e..1dcc2acd0 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -44,20 +44,29 @@ #include "net/base/net_errors.h" #include "qquickwebengineloadrequest_p.h" +#include "render_widget_host_view_qt_delegate_quick.h" +#include "ui_delegates_manager.h" #include "web_contents_adapter.h" #include "web_engine_error.h" -#include "render_widget_host_view_qt_delegate_quick.h" +#include <QQmlEngine> +#include <QQmlComponent> +#include <QQmlContext> +#include <QQmlProperty> #include <QScreen> +#include <QStringBuilder> #include <QUrl> #include <QQmlEngine> +#include <private/qqmlmetatype_p.h> + QT_BEGIN_NAMESPACE QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate() : adapter(new WebContentsAdapter(qApp->property("QQuickWebEngineView_DisableHardwareAcceleration").toBool() ? SoftwareRenderingMode : HardwareAccelerationMode)) , e(new QQuickWebEngineViewExperimental(this)) , v(new QQuickWebEngineViewport(this)) + , contextMenuExtraItems(0) , loadProgress(0) , inspectable(false) , m_isLoading(false) @@ -94,6 +103,14 @@ QQuickWebEngineViewport *QQuickWebEngineViewPrivate::viewport() const return v.data(); } +UIDelegatesManager *QQuickWebEngineViewPrivate::ui() +{ + Q_Q(QQuickWebEngineView); + if (m_uIDelegatesManager.isNull()) + m_uIDelegatesManager.reset(new UIDelegatesManager(q)); + return m_uIDelegatesManager.data(); +} + RenderWidgetHostViewQtDelegate *QQuickWebEngineViewPrivate::CreateRenderWidgetHostViewQtDelegate(RenderWidgetHostViewQtDelegateClient *client, RenderingMode mode) { #if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)) @@ -103,6 +120,63 @@ RenderWidgetHostViewQtDelegate *QQuickWebEngineViewPrivate::CreateRenderWidgetHo return new RenderWidgetHostViewQtDelegateQuickPainted(client); } +bool QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenuData &data) +{ + Q_Q(QQuickWebEngineView); + + QObject *menu = ui()->addMenu(0, QString(), data.pos); + if (!menu) + return false; + + // Populate our menu + MenuItemHandler *item = 0; + + if (data.selectedText.isEmpty()) { + item = new MenuItemHandler(menu); + QObject::connect(item, &MenuItemHandler::triggered, q, &QQuickWebEngineView::goBack); + ui()->addMenuItem(item, QObject::tr("Back"), QStringLiteral("go-previous"), q->canGoBack()); + + item = new MenuItemHandler(menu); + QObject::connect(item, &MenuItemHandler::triggered, q, &QQuickWebEngineView::goForward); + ui()->addMenuItem(item, QObject::tr("Forward"), QStringLiteral("go-next"), q->canGoForward()); + + item = new MenuItemHandler(menu); + QObject::connect(item, &MenuItemHandler::triggered, q, &QQuickWebEngineView::reload); + ui()->addMenuItem(item, QObject::tr("Reload"), QStringLiteral("view-refresh")); + } else { + item = new CopyMenuItem(menu, data.selectedText); + ui()->addMenuItem(item, QObject::tr("Copy...")); + } + + if (!data.linkText.isEmpty() && data.linkUrl.isValid()) { + item = new NavigateMenuItem(menu, adapter, data.linkUrl); + ui()->addMenuItem(item, QObject::tr("Navigate to...")); + item = new CopyMenuItem(menu, data.linkUrl.toString()); + ui()->addMenuItem(item, QObject::tr("Copy link address")); + } + + // 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(ui()->creationContextForComponent(contextMenuExtraItems))) { + menuExtras->setParent(menu); + QQmlListReference entries(menu, QQmlMetaType::defaultProperty(menu).name(), qmlEngine(q)); + if (entries.isValid()) + entries.append(menuExtras); + } + } + + // Now fire the popup() method on the top level menu + QMetaObject::invokeMethod(menu, "popup"); + return true; +} + +bool QQuickWebEngineViewPrivate::javascriptDialog(JavascriptDialogType type, const QString &message, const QString &defaultValue, QString *result) +{ + Q_UNUSED(message); Q_UNUSED(defaultValue); Q_UNUSED(result); + return false; +} + void QQuickWebEngineViewPrivate::titleChanged(const QString &title) { Q_Q(QQuickWebEngineView); @@ -338,6 +412,19 @@ void QQuickWebEngineView::setInspectable(bool enable) d->adapter->enableInspector(enable); } +void QQuickWebEngineViewExperimental::setExtraContextMenuEntriesComponent(QQmlComponent *contextMenuExtras) +{ + if (d_ptr->contextMenuExtraItems == contextMenuExtras) + return; + d_ptr->contextMenuExtraItems = contextMenuExtras; + emit extraContextMenuEntriesComponentChanged(); +} + +QQmlComponent *QQuickWebEngineViewExperimental::extraContextMenuEntriesComponent() const +{ + return d_ptr->contextMenuExtraItems; +} + void QQuickWebEngineView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { QQuickItem::geometryChanged(newGeometry, oldGeometry); diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h index 110a1b9b6..67337baeb 100644 --- a/src/webengine/api/qquickwebengineview_p_p.h +++ b/src/webengine/api/qquickwebengineview_p_p.h @@ -47,13 +47,17 @@ #include <QScopedPointer> #include <QSharedData> +#include <QString> #include <QtCore/qcompilerdetection.h> #include <QtQuick/private/qquickitem_p.h> class WebContentsAdapter; +class UIDelegatesManager; QT_BEGIN_NAMESPACE class QQuickWebEngineView; +class QQmlComponent; +class QQmlContext; class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineViewport : public QObject { Q_OBJECT @@ -88,12 +92,17 @@ private: class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineViewExperimental : public QObject { Q_OBJECT Q_PROPERTY(QQuickWebEngineViewport *viewport READ viewport) + Q_PROPERTY(QQmlComponent *extraContextMenuEntriesComponent READ extraContextMenuEntriesComponent WRITE setExtraContextMenuEntriesComponent NOTIFY extraContextMenuEntriesComponentChanged) + public: QQuickWebEngineViewport *viewport() const; Q_INVOKABLE void adoptHandle(QQuickWebEngineViewHandle *viewHandle); + void setExtraContextMenuEntriesComponent(QQmlComponent *); + QQmlComponent *extraContextMenuEntriesComponent() const; Q_SIGNALS: void createWindow(const QJSValue &newViewHandle, const QString &newViewDisposition); + void extraContextMenuEntriesComponentChanged(); private: QQuickWebEngineViewExperimental(QQuickWebEngineViewPrivate* viewPrivate); @@ -112,6 +121,7 @@ public: QQuickWebEngineViewExperimental *experimental() const; QQuickWebEngineViewport *viewport() const; + UIDelegatesManager *ui(); virtual RenderWidgetHostViewQtDelegate* CreateRenderWidgetHostViewQtDelegate(RenderWidgetHostViewQtDelegateClient *client, RenderingMode) Q_DECL_OVERRIDE; virtual void titleChanged(const QString&) Q_DECL_OVERRIDE; @@ -125,8 +135,8 @@ public: virtual void focusContainer() Q_DECL_OVERRIDE; virtual void adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition, const QRect &) Q_DECL_OVERRIDE; virtual void close() Q_DECL_OVERRIDE; - virtual bool contextMenuRequested(const WebEngineContextMenuData &) Q_DECL_OVERRIDE { return false;} - virtual bool javascriptDialog(JavascriptDialogType type, const QString &message, const QString &defaultValue = QString(), QString *result = 0) Q_DECL_OVERRIDE { return false; } + virtual bool contextMenuRequested(const WebEngineContextMenuData &) Q_DECL_OVERRIDE; + virtual bool javascriptDialog(JavascriptDialogType, const QString &message, const QString &defaultValue = QString(), QString *result = 0) Q_DECL_OVERRIDE { Q_UNUSED(message); Q_UNUSED(defaultValue); Q_UNUSED(result); return false; } virtual void runFileChooser(FileChooserMode, const QString &defaultFileName, const QStringList &acceptedMimeTypes) { Q_UNUSED(defaultFileName); Q_UNUSED(acceptedMimeTypes);} void setDevicePixelRatio(qreal); @@ -134,6 +144,7 @@ public: QExplicitlySharedDataPointer<WebContentsAdapter> adapter; QScopedPointer<QQuickWebEngineViewExperimental> e; QScopedPointer<QQuickWebEngineViewport> v; + QQmlComponent *contextMenuExtraItems; QUrl icon; int loadProgress; bool inspectable; @@ -141,6 +152,7 @@ public: qreal devicePixelRatio; private: + QScopedPointer<UIDelegatesManager> m_uIDelegatesManager; qreal m_dpiScale; }; diff --git a/src/webengine/ui/Menu.qml b/src/webengine/ui/Menu.qml new file mode 100644 index 000000000..e9cd25ed1 --- /dev/null +++ b/src/webengine/ui/Menu.qml @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Controls 1.0 as Controls + +Controls.Menu { + signal done() + + // Use private API for now + on__MenuClosed: done(); +} diff --git a/src/webengine/ui/MenuItem.qml b/src/webengine/ui/MenuItem.qml new file mode 100644 index 000000000..25b4ecb2b --- /dev/null +++ b/src/webengine/ui/MenuItem.qml @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Controls 1.0 as Controls + +Controls.MenuItem { } + diff --git a/src/webengine/ui/MenuSeparator.qml b/src/webengine/ui/MenuSeparator.qml new file mode 100644 index 000000000..b04d61b35 --- /dev/null +++ b/src/webengine/ui/MenuSeparator.qml @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Controls 1.0 as Controls + +Controls.MenuSeparator { } diff --git a/src/webengine/ui/qmldir b/src/webengine/ui/qmldir new file mode 100644 index 000000000..bc0e2e300 --- /dev/null +++ b/src/webengine/ui/qmldir @@ -0,0 +1,4 @@ +module QtWebEngine.UIDelegates +Menu 1.0 Menu.qml +MenuItem 1.0 MenuItem.qml +MenuSeparator 1.0 MenuSeparator.qml diff --git a/src/webengine/ui/ui.pro b/src/webengine/ui/ui.pro new file mode 100644 index 000000000..42a5777dc --- /dev/null +++ b/src/webengine/ui/ui.pro @@ -0,0 +1,8 @@ +TARGETPATH = QtWebEngine/UIDelegates + +QML_FILES += \ + Menu.qml \ + MenuItem.qml \ + MenuSeparator.qml + +load(qml_module) diff --git a/src/webengine/ui_delegates_manager.cpp b/src/webengine/ui_delegates_manager.cpp new file mode 100644 index 000000000..34edbd479 --- /dev/null +++ b/src/webengine/ui_delegates_manager.cpp @@ -0,0 +1,233 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "ui_delegates_manager.h" +#include "api/qquickwebengineview_p.h" + +#include <QAbstractListModel> +#include <QClipboard> +#include <QFileInfo> +#include <QGuiApplication> +#include <QQmlContext> +#include <QQmlEngine> +#include <QQmlProperty> +#include <QStringBuilder> +#include <private/qqmlmetatype_p.h> + +// Uncomment for QML debugging +//#define UI_DELEGATES_DEBUG + +#define NO_SEPARATOR +#define FILE_NAME_CASE_STATEMENT(TYPE, COMPONENT) \ + case UIDelegatesManager::TYPE:\ + return QStringLiteral(#TYPE".qml"); + +static QString fileNameForComponent(UIDelegatesManager::ComponentType type) +{ + switch (type) { + FOR_EACH_COMPONENT_TYPE(FILE_NAME_CASE_STATEMENT, NO_SEPARATOR) + default: + Q_UNREACHABLE(); + } + return QString(); +} + +MenuItemHandler::MenuItemHandler(QObject *parent) + : QObject(parent) +{ +} + + +CopyMenuItem::CopyMenuItem(QObject *parent, const QString &textToCopy) + : MenuItemHandler(parent) + , m_textToCopy(textToCopy) +{ + connect(this, &MenuItemHandler::triggered, this, &CopyMenuItem::onTriggered); +} + +void CopyMenuItem::onTriggered() +{ + qApp->clipboard()->setText(m_textToCopy); +} + +NavigateMenuItem::NavigateMenuItem(QObject *parent, const QExplicitlySharedDataPointer<WebContentsAdapter> &adapter, const QUrl &targetUrl) + : MenuItemHandler(parent) + , m_adapter(adapter) + , m_targetUrl(targetUrl) +{ + connect(this, &MenuItemHandler::triggered, this, &NavigateMenuItem::onTriggered); +} + +void NavigateMenuItem::onTriggered() +{ + m_adapter->load(m_targetUrl); +} + +UIDelegatesManager::UIDelegatesManager(QQuickWebEngineView *view) + : m_view(view) +{ +} + +#define COMPONENT_MEMBER_CASE_STATEMENT(TYPE, COMPONENT) \ + case TYPE: \ + component = &COMPONENT##Component; \ + break; + +bool UIDelegatesManager::ensureComponentLoaded(ComponentType type) +{ + QScopedPointer<QQmlComponent> *component; + switch (type) { + FOR_EACH_COMPONENT_TYPE(COMPONENT_MEMBER_CASE_STATEMENT, NO_SEPARATOR) + default: + Q_UNREACHABLE(); + return false; + } + QString fileName(fileNameForComponent(type)); +#ifndef UI_DELEGATES_DEBUG + if (!(*component).isNull()) + return true; +#else // Unconditionally reload the components each time. + fprintf(stderr, "%s: %s\n", Q_FUNC_INFO, qPrintable(fileName)); +#endif + QQmlEngine* engine = qmlEngine(m_view); + if (!engine) + return false; + QString absolutePath; + Q_FOREACH (const QString &path, engine->importPathList()) { + QFileInfo fi(path % QStringLiteral("/QtWebEngine/UIDelegates/") % fileName); + if (fi.exists()) + absolutePath = fi.absoluteFilePath(); + } + // FIXME: handle async loading + (*component).reset(new QQmlComponent(engine, QUrl(absolutePath), QQmlComponent::PreferSynchronous, m_view)); + + if ((*component)->status() != QQmlComponent::Ready) { +#ifdef UI_DELEGATES_DEBUG + Q_FOREACH (const QQmlError& err, (*component)->errors()) + fprintf(stderr, " component error: %s\n", qPrintable(err.toString())); +#endif + return false; + } + return true; +} + +QQmlContext *UIDelegatesManager::creationContextForComponent(QQmlComponent *component) +{ + Q_ASSERT(component); + + QQmlContext* baseContext = component->creationContext() ? component->creationContext() : qmlContext(m_view); + Q_ASSERT(baseContext); + return baseContext; +} + +#define CHECK_QML_SIGNAL_PROPERTY(prop, type, location) \ + if (!prop.isSignalProperty()) \ + qWarning(#type "component (Loaded from %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) +{ + Q_ASSERT(menuItemHandler); + if (!ensureComponentLoaded(MenuItem)) + return; + QObject *it = menuItemComponent->beginCreate(creationContextForComponent(menuItemComponent.data())); + + QQmlProperty(it, QStringLiteral("text")).write(text); + QQmlProperty(it, QStringLiteral("iconName")).write(iconName); + QQmlProperty(it, QStringLiteral("enabled")).write(enabled); + + QQmlProperty signal(it, QStringLiteral("onTriggered")); + CHECK_QML_SIGNAL_PROPERTY(signal, menuItemComponent->url()); + QObject::connect(it, signal.method(), menuItemHandler, QMetaMethod::fromSignal(&MenuItemHandler::triggered)); + menuItemComponent->completeCreate(); + + QObject *menu = menuItemHandler->parent(); + it->setParent(menu); + + QQmlListReference entries(menu, QQmlMetaType::defaultProperty(menu).name(), qmlEngine(m_view)); + if (entries.isValid()) + entries.append(it); +} + +void UIDelegatesManager::addMenuSeparator(QObject *menu) +{ + if (!ensureComponentLoaded(MenuSeparator)) + return; + + QQmlContext *itemContext = creationContextForComponent(menuSeparatorComponent.data()); + QObject *sep = menuSeparatorComponent->create(itemContext); + sep->setParent(menu); + + QQmlListReference entries(menu, QQmlMetaType::defaultProperty(menu).name(), qmlEngine(m_view)); + if (entries.isValid()) + entries.append(sep); +} + +QObject *UIDelegatesManager::addMenu(QObject *parentMenu, const QString &title, const QPoint& pos) +{ + + if (!ensureComponentLoaded(Menu)) + return 0; + QQmlContext *context(creationContextForComponent(menuComponent.data())); + QObject *menu = menuComponent->beginCreate(context); + // Useful when not using Qt Quick Controls' Menu + if (QQuickItem* item = qobject_cast<QQuickItem*>(menu)) + item->setParentItem(m_view); + + if (!title.isEmpty()) + QQmlProperty(menu, QStringLiteral("title")).write(title); + if (!pos.isNull()) + QQmlProperty(menu, QStringLiteral("pos")).write(pos); + if (!parentMenu) { + QQmlProperty doneSignal(menu, QStringLiteral("onDone")); + static int deleteLaterIndex = menu->metaObject()->indexOfSlot("deleteLater()"); + if (doneSignal.isSignalProperty()) + QObject::connect(menu, doneSignal.method(), menu, menu->metaObject()->method(deleteLaterIndex)); + } else { + menu->setParent(parentMenu); + + QQmlListReference entries(parentMenu, QQmlMetaType::defaultProperty(parentMenu).name(), qmlEngine(m_view)); + if (entries.isValid()) + entries.append(menu); + } + menuComponent->completeCreate(); + return menu; +} + diff --git a/src/webengine/ui_delegates_manager.h b/src/webengine/ui_delegates_manager.h new file mode 100644 index 000000000..65f994b93 --- /dev/null +++ b/src/webengine/ui_delegates_manager.h @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef UI_DELEGATES_MANAGER_H +#define UI_DELEGATES_MANAGER_H + +#include "qglobal.h" +#include "web_contents_adapter.h" + +#include <QExplicitlySharedDataPointer> +#include <QPoint> +#include <QPointer> +#include <QQmlComponent> +#include <QUrl> + +#define FOR_EACH_COMPONENT_TYPE(F, SEPARATOR) \ + F(Menu, menu) SEPARATOR \ + F(MenuItem, menuItem) SEPARATOR \ + F(MenuSeparator, menuSeparator) SEPARATOR + +#define COMMA_SEPARATOR , +#define SEMICOLON_SEPARATOR ; +#define ENUM_DECLARATION(TYPE, COMPONENT) \ + TYPE +#define MEMBER_DECLARATION(TYPE, COMPONENT) \ + QScopedPointer<QQmlComponent> COMPONENT##Component + +QT_BEGIN_NAMESPACE +class QObject; +class QQmlContext; +class QQuickWebEngineView; +QT_END_NAMESPACE + + +class MenuItemHandler : public QObject { +Q_OBJECT +public: + MenuItemHandler(QObject *parent); + +Q_SIGNALS: + void triggered(); +}; + +class CopyMenuItem : public MenuItemHandler { + Q_OBJECT +public: + CopyMenuItem(QObject *parent, const QString &textToCopy); + +private: + void onTriggered(); + + QString m_textToCopy; +}; + +class NavigateMenuItem : public MenuItemHandler { + Q_OBJECT +public: + NavigateMenuItem(QObject *parent, const QExplicitlySharedDataPointer<WebContentsAdapter> &adapter, const QUrl &targetUrl); + +private: + void onTriggered(); + + QExplicitlySharedDataPointer<WebContentsAdapter> m_adapter; + QUrl m_targetUrl; +}; + +class UIDelegatesManager { + +public: + enum ComponentType { + FOR_EACH_COMPONENT_TYPE(ENUM_DECLARATION, COMMA_SEPARATOR) + }; + + UIDelegatesManager(QQuickWebEngineView *); + + void addMenuItem(MenuItemHandler *menuItemHandler, const QString &text, const QString &iconName = QString(), bool enabled = true); + void addMenuSeparator(QObject *menu); + QObject *addMenu(QObject *parentMenu, const QString &title, const QPoint &pos = QPoint()); + QQmlContext *creationContextForComponent(QQmlComponent *); + +private: + bool ensureComponentLoaded(ComponentType); + + QQuickWebEngineView *m_view; + + FOR_EACH_COMPONENT_TYPE(MEMBER_DECLARATION, SEMICOLON_SEPARATOR) + + Q_DISABLE_COPY(UIDelegatesManager); + +}; + +#endif // UI_DELEGATES_MANAGER_H diff --git a/src/webengine/webengine.pro b/src/webengine/webengine.pro index 96724d465..877c515a9 100644 --- a/src/webengine/webengine.pro +++ b/src/webengine/webengine.pro @@ -22,7 +22,8 @@ QMAKE_RPATHDIR += $$LIBPATH SOURCES = \ api/qquickwebengineloadrequest.cpp \ api/qquickwebengineview.cpp \ - render_widget_host_view_qt_delegate_quick.cpp + render_widget_host_view_qt_delegate_quick.cpp \ + ui_delegates_manager.cpp HEADERS = \ api/qtwebengineglobal.h \ @@ -30,6 +31,7 @@ HEADERS = \ api/qquickwebengineloadrequest_p.h \ api/qquickwebengineview_p.h \ api/qquickwebengineview_p_p.h \ - render_widget_host_view_qt_delegate_quick.h + render_widget_host_view_qt_delegate_quick.h \ + ui_delegates_manager.h load(qt_module) |