diff options
author | Christian Strømme <[email protected]> | 2015-01-16 11:04:58 +0100 |
---|---|---|
committer | Christian Stromme <[email protected]> | 2015-02-09 16:35:06 +0000 |
commit | 56da39587414f127774e1b5e9f88a84f8f27db08 (patch) | |
tree | 5d7bcc9e60df41ca8c70b3ae1ad1adeff4bc5669 | |
parent | ea443a6960316d5070c1a3a5dbe21037a96ff7e4 (diff) |
Refactor QWebView code.
In an attempt to make the code more future proof, this patch tries to
improve the abstraction between the native WebViews/View controllers
and the public APIs. This should make it easier to add new platforms
and alternative public interfaces, e.g., a Window/Widget API. It should
also make it easier to implement a plugin system if needed.
In addition the following changes were done:
- reload() implementation in the android controller.
- reload() calls the native reload function on both Android and iOS.
- loadProgress() calls the native getProgress() directly on Android.
- isLoading() calls loading() on the UIWebView (iOS)
- runJavaScript() will now only pass the script and an id to the platform
implementation to avoid creating a strong coupling to QJSValue.
Change-Id: I3cbd81c7fd8d93bacf9134be32ad061d1f9e1183
Reviewed-by: Friedemann Kleint <[email protected]>
Reviewed-by: Eskil Abrahamsen Blomfeldt <[email protected]>
-rw-r--r-- | src/imports/webview.cpp | 4 | ||||
-rw-r--r-- | src/jar/src/org/qtproject/qt5/android/view/QtAndroidWebViewController.java | 53 | ||||
-rw-r--r-- | src/webview/qnativeviewcontroller_p.h | 61 | ||||
-rw-r--r-- | src/webview/qquickviewcontroller.cpp (renamed from src/webview/qwindowcontrolleritem.cpp) | 47 | ||||
-rw-r--r-- | src/webview/qquickviewcontroller_p.h (renamed from src/webview/qwindowcontrolleritem_p.h) | 44 | ||||
-rw-r--r-- | src/webview/qquickwebview.cpp | 191 | ||||
-rw-r--r-- | src/webview/qquickwebview.h | 120 | ||||
-rw-r--r-- | src/webview/qwebview.cpp | 227 | ||||
-rw-r--r-- | src/webview/qwebview_android.cpp | 103 | ||||
-rw-r--r-- | src/webview/qwebview_android_p.h | 32 | ||||
-rw-r--r-- | src/webview/qwebview_default.cpp | 6 | ||||
-rw-r--r-- | src/webview/qwebview_ios.mm | 192 | ||||
-rw-r--r-- | src/webview/qwebview_ios_p.h | 37 | ||||
-rw-r--r-- | src/webview/qwebview_p.h | 131 | ||||
-rw-r--r-- | src/webview/qwebview_p_p.h | 71 | ||||
-rw-r--r-- | src/webview/qwebviewinterface_p.h (renamed from src/webview/qwebview_default_p.h) | 51 | ||||
-rw-r--r-- | src/webview/qwindowcontrolleritem_ios.mm | 152 | ||||
-rw-r--r-- | src/webview/webview-lib.pri | 39 |
18 files changed, 948 insertions, 613 deletions
diff --git a/src/imports/webview.cpp b/src/imports/webview.cpp index 6c6d145..72396f2 100644 --- a/src/imports/webview.cpp +++ b/src/imports/webview.cpp @@ -37,7 +37,7 @@ #include <QtQml/qqmlextensionplugin.h> #include <QtQml/qqml.h> -#include <QtWebView/private/qwebview_p.h> +#include <QtWebView/qquickwebview.h> QT_BEGIN_NAMESPACE @@ -51,7 +51,7 @@ public: Q_ASSERT(QLatin1String(uri) == QLatin1String("QtWebView")); // @uri QtWebView - qmlRegisterType<QWebView>(uri, 1, 0, "WebView"); + qmlRegisterType<QQuickWebView>(uri, 1, 0, "WebView"); } void initializeEngine(QQmlEngine *engine, const char *uri) diff --git a/src/jar/src/org/qtproject/qt5/android/view/QtAndroidWebViewController.java b/src/jar/src/org/qtproject/qt5/android/view/QtAndroidWebViewController.java index 78f8de1..dd3cab0 100644 --- a/src/jar/src/org/qtproject/qt5/android/view/QtAndroidWebViewController.java +++ b/src/jar/src/org/qtproject/qt5/android/view/QtAndroidWebViewController.java @@ -36,6 +36,7 @@ package org.qtproject.qt5.android.view; +import android.webkit.ValueCallback; import android.webkit.WebView; import android.webkit.WebViewClient; import android.webkit.WebChromeClient; @@ -169,6 +170,32 @@ public class QtAndroidWebViewController }); } + public void loadData(final String data, final String mimeType, final String encoding) + { + if (data == null) + return; + + m_activity.runOnUiThread(new Runnable() { + @Override + public void run() { m_webView.loadData(data, mimeType, encoding); } + }); + } + + public void loadDataWithBaseURL(final String baseUrl, + final String data, + final String mimeType, + final String encoding, + final String historyUrl) + { + if (data == null) + return; + + m_activity.runOnUiThread(new Runnable() { + @Override + public void run() { m_webView.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl); } + }); + } + public void goBack() { m_activity.runOnUiThread(new Runnable() { @@ -229,6 +256,14 @@ public class QtAndroidWebViewController }); } + public void reload() + { + m_activity.runOnUiThread(new Runnable() { + @Override + public void run() { m_webView.reload(); } + }); + } + public String getTitle() { final String[] title = {""}; @@ -247,6 +282,24 @@ public class QtAndroidWebViewController return title[0]; } + public int getProgress() + { + final int[] progress = {0}; + final Semaphore sem = new Semaphore(0); + m_activity.runOnUiThread(new Runnable() { + @Override + public void run() { progress[0] = m_webView.getProgress(); sem.release(); } + }); + + try { + sem.acquire(); + } catch (Exception e) { + e.printStackTrace(); + } + + return progress[0]; + } + public String getUrl() { final String[] url = {""}; diff --git a/src/webview/qnativeviewcontroller_p.h b/src/webview/qnativeviewcontroller_p.h new file mode 100644 index 0000000..1745c0f --- /dev/null +++ b/src/webview/qnativeviewcontroller_p.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebView 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNATIVEVIEWCONTROLLER_P_H +#define QNATIVEVIEWCONTROLLER_P_H + +#include "qwebview_global.h" +#include <QtCore/qrect.h> +#include <QtGui/qwindow.h> + +QT_BEGIN_NAMESPACE + +class QNativeViewController +{ +public: + virtual ~QNativeViewController() {} + virtual void setParentView(QObject *view) = 0; + virtual void setGeometry(const QRect &geometry) = 0; + virtual void setVisibility(QWindow::Visibility visibility) = 0; + virtual void setVisible(bool visible) = 0; + virtual void init() { } + virtual void setFocus(bool focus) { Q_UNUSED(focus); } +}; + +QT_END_NAMESPACE + +#endif // QNATIVEVIEWCONTROLLER_P_H + diff --git a/src/webview/qwindowcontrolleritem.cpp b/src/webview/qquickviewcontroller.cpp index 71c207b..bc48124 100644 --- a/src/webview/qwindowcontrolleritem.cpp +++ b/src/webview/qquickviewcontroller.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtWebView module of the Qt Toolkit. @@ -34,59 +34,54 @@ ** ****************************************************************************/ -#include "qwindowcontrolleritem_p.h" +#include "qquickviewcontroller_p.h" +#include "qwebview_p.h" #include <QtGui/QWindow> #include <QtQuick/QQuickWindow> #include <QtCore/QDebug> -QWindowControllerItem::QWindowControllerItem(QQuickItem *parent) +QQuickViewController::QQuickViewController(QQuickItem *parent) : QQuickItem(parent) - , m_controlledWindow(0) + , m_view(0) { - connect(this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(onWindowChanged(QQuickWindow*))); - connect(this, SIGNAL(visibleChanged()), this, SLOT(onVisibleChanged())); + connect(this, &QQuickViewController::windowChanged, this, &QQuickViewController::onWindowChanged); + connect(this, &QQuickViewController::visibleChanged, this, &QQuickViewController::onVisibleChanged); } -QWindowControllerItem::~QWindowControllerItem() +QQuickViewController::~QQuickViewController() { - delete m_controlledWindow; } -void QWindowControllerItem::setNativeWindow(WId windowId) +void QQuickViewController::componentComplete() { - Q_ASSERT(m_controlledWindow == 0); - m_controlledWindow = QWindow::fromWinId(windowId); - m_controlledWindow->setVisibility(QWindow::Windowed); + QQuickItem::componentComplete(); + m_view->init(); + m_view->setVisibility(QWindow::Windowed); } -void QWindowControllerItem::componentComplete() +void QQuickViewController::setView(QNativeViewController *view) { - QQuickItem::componentComplete(); + Q_ASSERT(m_view == 0); + m_view = view; } -void QWindowControllerItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +void QQuickViewController::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { QQuickItem::geometryChanged(newGeometry, oldGeometry); - if (!m_controlledWindow) - return; if (newGeometry.isValid()) - m_controlledWindow->setGeometry(mapRectToScene(newGeometry).toRect()); + m_view->setGeometry(mapRectToScene(newGeometry).toRect()); else qWarning() << __FUNCTION__ << "Invalid geometry: " << newGeometry; } -void QWindowControllerItem::onWindowChanged(QQuickWindow* window) +void QQuickViewController::onWindowChanged(QQuickWindow* window) { - if (!m_controlledWindow) - return; - - m_controlledWindow->setParent(window); + m_view->setParentView(window); } -void QWindowControllerItem::onVisibleChanged() +void QQuickViewController::onVisibleChanged() { - if (m_controlledWindow) - m_controlledWindow->setVisible(isVisible()); + m_view->setVisible(isVisible()); } diff --git a/src/webview/qwindowcontrolleritem_p.h b/src/webview/qquickviewcontroller_p.h index cd8f128..0e8d685 100644 --- a/src/webview/qwindowcontrolleritem_p.h +++ b/src/webview/qquickviewcontroller_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtWebView module of the Qt Toolkit. @@ -34,8 +34,8 @@ ** ****************************************************************************/ -#ifndef QWINDOWCONTROLLERITEM_H -#define QWINDOWCONTROLLERITEM_H +#ifndef QQUICKVIEWCONTROLLER_H +#define QQUICKVIEWCONTROLLER_H // // W A R N I N G @@ -51,38 +51,34 @@ #include <QtWebView/qwebview_global.h> #include <QtQuick/QQuickItem> +#include <QtGui/qwindow.h> -#ifdef Q_OS_IOS -Q_FORWARD_DECLARE_OBJC_CLASS(UIView); -Q_FORWARD_DECLARE_OBJC_CLASS(UIGestureRecognizer); -#endif +QT_BEGIN_NAMESPACE -class Q_WEBVIEW_EXPORT QWindowControllerItem : public QQuickItem +class QNativeViewController; + +class Q_WEBVIEW_EXPORT QQuickViewController : public QQuickItem { Q_OBJECT public: - explicit QWindowControllerItem(QQuickItem *parent = 0); - ~QWindowControllerItem(); - void setNativeWindow(WId windowId); -#ifndef Q_OS_IOS - QWindow *controlledWindow() const { return m_controlledWindow; } -#else - UIView *controlledWindow() const { return m_controlledUIView; } -#endif - void componentComplete(); - void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); + explicit QQuickViewController(QQuickItem *parent = 0); + ~QQuickViewController(); + + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; public slots: void onWindowChanged(QQuickWindow* window); void onVisibleChanged(); +protected: + void componentComplete() Q_DECL_OVERRIDE; + void setView(QNativeViewController *view); + private: -#ifdef Q_OS_IOS - UIView *m_controlledUIView; - UIGestureRecognizer *m_recognizer; -#else - QWindow *m_controlledWindow; -#endif + friend class QQuickWebView; + QNativeViewController *m_view; }; +QT_END_NAMESPACE + #endif // QTWINDOWCONTROLLERITEM_H diff --git a/src/webview/qquickwebview.cpp b/src/webview/qquickwebview.cpp new file mode 100644 index 0000000..be51fb7 --- /dev/null +++ b/src/webview/qquickwebview.cpp @@ -0,0 +1,191 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebView 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickwebview.h" +#include <QtQml/qqmlengine.h> +#include <QtCore/qmutex.h> + +/*! + \qmltype WebView + \inqmlmodule QtWebView + \ingroup qtwebview + \brief A component for displaying web content + + WebView is a component for displaying web content which is implemented using native + APIs on the platforms where this is available, thus it does not necessarily require + including a full web browser stack as part of the application. + + WebView is currently supported on the following platforms: Android. + + \note Due to platform limitations overlapping the WebView and other QML components + is not supported. +*/ + +QQuickWebView::QQuickWebView(QQuickItem *parent) + : QQuickViewController(parent) + , m_webView(new QWebView(this)) +{ + setView(m_webView.data()); + connect(m_webView.data(), &QWebView::titleChanged, this, &QQuickWebView::titleChanged); + connect(m_webView.data(), &QWebView::urlChanged, this, &QQuickWebView::urlChanged); + connect(m_webView.data(), &QWebView::loadingChanged, this, &QQuickWebView::loadingChanged); + connect(m_webView.data(), &QWebView::loadProgressChanged, this, &QQuickWebView::loadProgressChanged); + connect(m_webView.data(), &QWebView::requestFocus, this, &QQuickWebView::onFocusRequest); +} + +QQuickWebView::~QQuickWebView() +{ +} + +/*! + \qmlproperty url QtWebView::WebView::url + + The url of currently loaded web page. Changing this will trigger + loading new content. + + The url is used as-is. Urls that originate from user input should + be parsed with QUrl::fromUserInput. +*/ + +void QQuickWebView::setUrl(const QUrl &url) +{ + m_webView->setUrl(url); +} + +/*! + \qmlproperty string QtWebView::WebView::title + + The title of the currently loaded web page. +*/ + +QString QQuickWebView::title() const +{ + return m_webView->title(); +} + +QUrl QQuickWebView::url() const +{ + return m_webView->url(); +} + +/*! + \qmlproperty bool QtWebView::WebView::canGoBack + + True if it's currently possible to navigate back in the web history. +*/ + +bool QQuickWebView::canGoBack() const +{ + return m_webView->canGoBack(); +} + +/*! + \qmlproperty bool QtWebView::WebView::canGoForward + + True if it's currently possible to navigate forward in the web history. +*/ + +bool QQuickWebView::canGoForward() const +{ + return m_webView->canGoForward(); +} + +/*! + \qmlproperty int QtWebView::WebView::loadProgress + + The current load progress of the web content, represented as + an integer between 0 and 100. +*/ +int QQuickWebView::loadProgress() const +{ + return m_webView->loadProgress(); +} + +/*! + \qmlproperty bool QtWebView::WebView::loading + + True if the WebView is currently in the process of loading + new content, and false if not. +*/ +bool QQuickWebView::isLoading() const +{ + return m_webView->isLoading(); +} + +/*! + \qmlmethod void QtWebView::WebView::goBack() + + Navigates back in the web history. +*/ +void QQuickWebView::goBack() +{ + m_webView->goBack(); +} + +/*! + \qmlmethod void QtWebView::WebView::goForward() + + Navigates forward in the web history. +*/ +void QQuickWebView::goForward() +{ + m_webView->goForward(); +} + +/*! + \qmlmethod void QtWebView::WebView::reload() + + Reloads the current url. +*/ +void QQuickWebView::reload() +{ + m_webView->reload(); +} + +/*! + \qmlmethod void QtWebView::WebView::stop() + + Stops loading the current url. +*/ +void QQuickWebView::stop() +{ + m_webView->stop(); +} + +void QQuickWebView::onFocusRequest(bool focus) +{ + setFocus(focus); +} diff --git a/src/webview/qquickwebview.h b/src/webview/qquickwebview.h new file mode 100644 index 0000000..aab13b1 --- /dev/null +++ b/src/webview/qquickwebview.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebView 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKWEBVIEW_H +#define QQUICKWEBVIEW_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 "qwebviewinterface_p.h" + +#if !defined(QT_WEBVIEW_WEBENGINE_BACKEND) + +#include "qwebview_p.h" +#include "qquickviewcontroller_p.h" + +QT_BEGIN_NAMESPACE + +class Q_WEBVIEW_EXPORT QQuickWebView : public QQuickViewController, public QWebViewInterface +{ + Q_OBJECT + Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged) + Q_PROPERTY(bool loading READ isLoading NOTIFY loadingChanged) + Q_PROPERTY(int loadProgress READ loadProgress NOTIFY loadProgressChanged) + Q_PROPERTY(QString title READ title NOTIFY titleChanged) + Q_PROPERTY(bool canGoBack READ canGoBack NOTIFY loadingChanged) + Q_PROPERTY(bool canGoForward READ canGoForward NOTIFY loadingChanged) + +public: + QQuickWebView(QQuickItem *parent = 0); + ~QQuickWebView(); + + QUrl url() const Q_DECL_OVERRIDE; + void setUrl(const QUrl &url) Q_DECL_OVERRIDE; + int loadProgress() const Q_DECL_OVERRIDE; + QString title() const Q_DECL_OVERRIDE; + bool canGoBack() const Q_DECL_OVERRIDE; + bool isLoading() const Q_DECL_OVERRIDE; + bool canGoForward() const Q_DECL_OVERRIDE; + +public Q_SLOTS: + void goBack() Q_DECL_OVERRIDE; + void goForward() Q_DECL_OVERRIDE; + void reload() Q_DECL_OVERRIDE; + void stop() Q_DECL_OVERRIDE; + +Q_SIGNALS: + void titleChanged(); + void urlChanged(); + void loadingChanged(); + void loadProgressChanged(); + +private Q_SLOTS: + void onFocusRequest(bool focus); + +private: + QScopedPointer<QWebView> m_webView; +}; + +QT_END_NAMESPACE + +#else + +#include <QtWebEngine/private/qquickwebengineview_p.h> + +QT_BEGIN_NAMESPACE + +class Q_WEBVIEW_EXPORT QQuickWebView : public QQuickWebEngineView +{ + Q_OBJECT +public: + QQuickWebView(QQuickItem *parent = 0) : QQuickWebEngineView(parent) { } +}; + +QT_END_NAMESPACE + +#endif + +#endif // QQUICKWEBVIEW_H diff --git a/src/webview/qwebview.cpp b/src/webview/qwebview.cpp index 84f3175..9d55331 100644 --- a/src/webview/qwebview.cpp +++ b/src/webview/qwebview.cpp @@ -38,247 +38,122 @@ QT_BEGIN_NAMESPACE -QWebViewPrivate::QWebViewPrivate(QWebView *q) - : m_loadProgress(0) - , m_loading(false) - , q_ptr(q) +QWebView::QWebView(QObject *p) + : QObject(p), + d_ptr(QWebViewPrivate::create(this)) { - connect(this,SIGNAL(pageStarted(QString)),SLOT(onPageStartedPrivate(QString))); - connect(this,SIGNAL(pageFinished(QString)),SLOT(onPageFinishedPrivate(QString))); - connect(this,SIGNAL(titleChanged(QString)),SLOT(onTitleChangedPrivate(QString))); - connect(this,SIGNAL(progressChanged(int)),SLOT(onProgressChangedPrivate(int))); + Q_D(QWebView); + connect(d, SIGNAL(titleChanged()), this, SIGNAL(titleChanged())); + connect(d, SIGNAL(urlChanged()), this, SIGNAL(urlChanged())); + connect(d, SIGNAL(loadingChanged()), this, SIGNAL(loadingChanged())); + connect(d, SIGNAL(loadProgressChanged()), this, SIGNAL(loadProgressChanged())); + connect(d, SIGNAL(requestFocus(bool)), this, SIGNAL(requestFocus(bool))); } -QWebViewPrivate::~QWebViewPrivate() +QWebView::~QWebView() { } -void QWebViewPrivate::onPageStartedPrivate(QString url) +QUrl QWebView::url() const { - Q_Q(QWebView); - const QUrl newUrl = QUrl::fromUserInput(url); - if (m_url != newUrl) { - m_url = newUrl; - Q_EMIT q->urlChanged(); - } - - if (!m_loading) { - m_loading = true; - Q_EMIT q->loadingChanged(); - } + Q_D(const QWebView); + return d->url(); } -void QWebViewPrivate::onPageFinishedPrivate(QString url) +void QWebView::setUrl(const QUrl &url) { - Q_Q(QWebView); - const QUrl newUrl = QUrl::fromUserInput(url); - if (m_url != newUrl) { - m_url = newUrl; - Q_EMIT q->urlChanged(); - } - - if (m_loading) { - m_loading = false; - Q_EMIT q->loadingChanged(); - } + Q_D(QWebView); + d->setUrl(url); } -void QWebViewPrivate::onTitleChangedPrivate(QString title) +bool QWebView::canGoBack() const { - Q_Q(QWebView); - if (m_title == title) - return; - - m_title = title; - Q_EMIT q->titleChanged(); + Q_D(const QWebView); + return d->canGoBack(); } -void QWebViewPrivate::onProgressChangedPrivate(int progress) +void QWebView::goBack() { - Q_Q(QWebView); - if (m_loadProgress == progress) - return; - - m_loadProgress = progress; - Q_EMIT q->loadProgressChanged(); + Q_D(QWebView); + d->goBack(); } -// This is called by QWindowControllerItem::componentComplete -// to create the native web view on the parent window. Alternatively, -// it can be called from QWebViewPrivate::create() if no delayed -// creation is desired. -void QWebViewPrivate::ensureNativeWebView() +bool QWebView::canGoForward() const { - Q_Q(QWebView); - if (q->controlledWindow()) - return; - if (const WId id = WId(nativeWebView())) - q->setNativeWindow(id); - else - qWarning("No native web view. Missing platform support?"); + Q_D(const QWebView); + return d->canGoForward(); } -/*! - \qmltype WebView - \inqmlmodule QtWebView - \ingroup qtwebview - \brief A component for displaying web content - - WebView is a component for displaying web content which is implemented using native - APIs on the platforms where this is available, thus it does not necessarily require - including a full web browser stack as part of the application. - - WebView is currently supported on the following platforms: Android. - - \note Due to platform limitations overlapping the WebView and other QML components - is not supported. -*/ - -QWebView::QWebView(QQuickItem *parent) - : QWindowControllerItem(parent) - , d_ptr(QWebViewPrivate::create(this)) +void QWebView::goForward() { + Q_D(QWebView); + d->goForward(); } -QWebView::~QWebView() +void QWebView::reload() { + Q_D(QWebView); + d->reload(); } -/*! - \qmlproperty url QtWebView::WebView::url - - The url of currently loaded web page. Changing this will trigger - loading new content. - - The url is used as-is. Urls that originate from user input should - be parsed with QUrl::fromUserInput. -*/ - -void QWebView::setUrl(const QUrl &url) +void QWebView::stop() { Q_D(QWebView); - if (d->m_url == url) - return; - - d->loadUrl(url.toString()); + d->stop(); } -/*! - \qmlproperty string QtWebView::WebView::title - - The title of the currently loaded web page. -*/ - QString QWebView::title() const { Q_D(const QWebView); - return d->m_title; -} - -QUrl QWebView::url() const -{ - Q_D(const QWebView); - return d->m_url; -} - -/*! - \qmlproperty bool QtWebView::WebView::canGoBack - - True if it's currently possible to navigate back in the web history. -*/ - -bool QWebView::canGoBack() const -{ - Q_D(const QWebView); - return d->canGoBack(); -} - -/*! - \qmlproperty bool QtWebView::WebView::canGoForward - - True if it's currently possible to navigate forward in the web history. -*/ - -bool QWebView::canGoForward() const -{ - Q_D(const QWebView); - return d->canGoForward(); + return d->title(); } -/*! - \qmlproperty int QtWebView::WebView::loadProgress - - The current load progress of the web content, represented as - an integer between 0 and 100. -*/ int QWebView::loadProgress() const { Q_D(const QWebView); - return d->m_loadProgress; + return d->loadProgress(); } -/*! - \qmlproperty bool QtWebView::WebView::loading - - True if the WebView is currently in the process of loading - new content, and false if not. -*/ bool QWebView::isLoading() const { Q_D(const QWebView); - return d->m_loading; + return d->isLoading(); } -/*! - \qmlmethod void QtWebView::WebView::goBack() - - Navigates back in the web history. -*/ -void QWebView::goBack() +void QWebView::setParentView(QObject *view) { Q_D(QWebView); - d->goBack(); + d->setParentView(view); } -/*! - \qmlmethod void QtWebView::WebView::goForward() - - Navigates forward in the web history. -*/ -void QWebView::goForward() +void QWebView::setGeometry(const QRect &geometry) { Q_D(QWebView); - d->goForward(); + d->setGeometry(geometry); } -/*! - \qmlmethod void QtWebView::WebView::reload() - - Reloads the current url. -*/ -void QWebView::reload() +void QWebView::setVisibility(QWindow::Visibility visibility) { Q_D(QWebView); - if (d->m_url.isValid()) - d->loadUrl(d->m_url.toString()); + d->setVisibility(visibility); } -/*! - \qmlmethod void QtWebView::WebView::stop() +void QWebView::setVisible(bool visible) +{ + Q_D(QWebView); + d->setVisible(visible); +} - Stops loading the current url. -*/ -void QWebView::stop() +void QWebView::setFocus(bool focus) { Q_D(QWebView); - d->stopLoading(); + d->setFocus(focus); } -void QWebView::componentComplete() +void QWebView::init() { Q_D(QWebView); - QWindowControllerItem::componentComplete(); - d->ensureNativeWebView(); + d->init(); } QT_END_NAMESPACE diff --git a/src/webview/qwebview_android.cpp b/src/webview/qwebview_android.cpp index b54ea14..be87a56 100644 --- a/src/webview/qwebview_android.cpp +++ b/src/webview/qwebview_android.cpp @@ -34,26 +34,27 @@ ** ****************************************************************************/ -#include "qwebview_p.h" #include "qwebview_android_p.h" +#include "qwebview_p.h" #include <QtCore/private/qjnihelpers_p.h> #include <QtCore/private/qjni_p.h> #include <QtCore/qmap.h> #include <android/bitmap.h> #include <QtGui/qguiapplication.h> +#include <QtCore/qjsondocument.h> +#include <QtCore/qjsonobject.h> +#include <QtCore/qurl.h> QT_BEGIN_NAMESPACE -static const char qtAndroidWebViewControllerClass[] = "org/qtproject/qt5/android/view/QtAndroidWebViewController"; - QWebViewPrivate *QWebViewPrivate::create(QWebView *q) { - QWebViewPrivate *result = new QAndroidWebViewPrivate(q); - result->ensureNativeWebView(); - return result; + return new QAndroidWebViewPrivate(q); } +static const char qtAndroidWebViewControllerClass[] = "org/qtproject/qt5/android/view/QtAndroidWebViewController"; + //static bool favIcon(JNIEnv *env, jobject icon, QImage *image) //{ // // TODO: @@ -71,12 +72,14 @@ QWebViewPrivate *QWebViewPrivate::create(QWebView *q) // return true; //} -typedef QMap<quintptr, QWebViewPrivate *> WebViews; +typedef QMap<quintptr, QAndroidWebViewPrivate *> WebViews; Q_GLOBAL_STATIC(WebViews, g_webViews) -QAndroidWebViewPrivate::QAndroidWebViewPrivate(QWebView *q) - : QWebViewPrivate(q) +QAndroidWebViewPrivate::QAndroidWebViewPrivate(QObject *p) + : QWebViewPrivate(p) , m_id(reinterpret_cast<quintptr>(this)) + , m_callbackId(0) + , m_window(0) { m_viewController = QJNIObjectPrivate(qtAndroidWebViewControllerClass, "(Landroid/app/Activity;J)V", @@ -84,6 +87,8 @@ QAndroidWebViewPrivate::QAndroidWebViewPrivate(QWebView *q) m_id); m_webView = m_viewController.callObjectMethod("getWebView", "()Landroid/webkit/WebView;"); + + m_window = QWindow::fromWinId(reinterpret_cast<WId>(m_webView.object())); g_webViews->insert(m_id, this); connect(qApp, &QGuiApplication::applicationStateChanged, this, &QAndroidWebViewPrivate::onApplicationStateChanged); @@ -92,18 +97,19 @@ QAndroidWebViewPrivate::QAndroidWebViewPrivate(QWebView *q) QAndroidWebViewPrivate::~QAndroidWebViewPrivate() { g_webViews->take(m_id); + delete m_window; } -QString QAndroidWebViewPrivate::getUrl() const +QUrl QAndroidWebViewPrivate::url() const { - return m_viewController.callObjectMethod<jstring>("getUrl").toString(); + return QUrl::fromUserInput(m_viewController.callObjectMethod<jstring>("getUrl").toString()); } -void QAndroidWebViewPrivate::loadUrl(const QString &url) +void QAndroidWebViewPrivate::setUrl(const QUrl &url) { m_viewController.callMethod<void>("loadUrl", "(Ljava/lang/String;)V", - QJNIObjectPrivate::fromString(url).object()); + QJNIObjectPrivate::fromString(url.toString()).object()); } bool QAndroidWebViewPrivate::canGoBack() const @@ -111,7 +117,7 @@ bool QAndroidWebViewPrivate::canGoBack() const return m_viewController.callMethod<jboolean>("canGoBack"); } -void QAndroidWebViewPrivate::goBack() const +void QAndroidWebViewPrivate::goBack() { m_viewController.callMethod<void>("goBack"); } @@ -121,26 +127,61 @@ bool QAndroidWebViewPrivate::canGoForward() const return m_viewController.callMethod<jboolean>("canGoForward"); } -void QAndroidWebViewPrivate::goForward() const +void QAndroidWebViewPrivate::goForward() { m_viewController.callMethod<void>("goForward"); } -QString QAndroidWebViewPrivate::getTitle() const +void QAndroidWebViewPrivate::reload() +{ + m_viewController.callMethod<void>("reload"); +} + +QString QAndroidWebViewPrivate::title() const { return m_viewController.callObjectMethod<jstring>("getTitle").toString(); } -void QAndroidWebViewPrivate::stopLoading() const +void QAndroidWebViewPrivate::setGeometry(const QRect &geometry) { - m_viewController.callMethod<void>("stopLoading"); + m_window->setGeometry(geometry); +} + +void QAndroidWebViewPrivate::setVisibility(QWindow::Visibility visibility) +{ + m_window->setVisibility(visibility); } -void *QAndroidWebViewPrivate::nativeWebView() const +void QAndroidWebViewPrivate::setVisible(bool visible) { - return m_webView.object(); + m_window->setVisible(visible); } +int QAndroidWebViewPrivate::loadProgress() const +{ + return m_viewController.callMethod<jint>("getProgress"); +} + +bool QAndroidWebViewPrivate::isLoading() const +{ + return true; +} + +void QAndroidWebViewPrivate::setParentView(QObject *view) +{ + m_window->setParent(qobject_cast<QWindow *>(view)); +} + +void QAndroidWebViewPrivate::stop() +{ + m_viewController.callMethod<void>("stopLoading"); +} + +//void QAndroidWebViewPrivate::initialize() +//{ +// // TODO: +//} + void QAndroidWebViewPrivate::onApplicationStateChanged(Qt::ApplicationState state) { if (QtAndroidPrivate::androidSdkVersion() < 11) @@ -162,11 +203,12 @@ static void c_onPageFinished(JNIEnv *env, Q_UNUSED(env) Q_UNUSED(thiz) const WebViews &wv = (*g_webViews); - QWebViewPrivate *wc = wv[id]; + QAndroidWebViewPrivate *wc = wv[id]; if (!wc) return; - Q_EMIT wc->pageFinished(QJNIObjectPrivate(url).toString()); + Q_UNUSED(url) // TODO: + Q_EMIT wc->loadingChanged(); } static void c_onPageStarted(JNIEnv *env, @@ -179,11 +221,12 @@ static void c_onPageStarted(JNIEnv *env, Q_UNUSED(thiz) Q_UNUSED(icon) const WebViews &wv = (*g_webViews); - QWebViewPrivate *wc = wv[id]; + QAndroidWebViewPrivate *wc = wv[id]; if (!wc) return; - Q_EMIT wc->pageStarted(QJNIObjectPrivate(url).toString()); + Q_UNUSED(url) // TODO: + Q_EMIT wc->loadingChanged(); // if (!icon) // return; @@ -201,11 +244,12 @@ static void c_onProgressChanged(JNIEnv *env, Q_UNUSED(env) Q_UNUSED(thiz) const WebViews &wv = (*g_webViews); - QWebViewPrivate *wc = wv[id]; + QAndroidWebViewPrivate *wc = wv[id]; if (!wc) return; - Q_EMIT wc->progressChanged(newProgress); + Q_UNUSED(newProgress) // TODO: + Q_EMIT wc->loadProgressChanged(); } static void c_onReceivedIcon(JNIEnv *env, @@ -219,7 +263,7 @@ static void c_onReceivedIcon(JNIEnv *env, Q_UNUSED(icon) const WebViews &wv = (*g_webViews); - QWebViewPrivate *wc = wv[id]; + QAndroidWebViewPrivate *wc = wv[id]; if (!wc) return; @@ -239,11 +283,12 @@ static void c_onReceivedTitle(JNIEnv *env, Q_UNUSED(env) Q_UNUSED(thiz) const WebViews &wv = (*g_webViews); - QWebViewPrivate *wc = wv[id]; + QAndroidWebViewPrivate *wc = wv[id]; if (!wc) return; - Q_EMIT wc->titleChanged(QJNIObjectPrivate(title).toString()); + Q_UNUSED(title) // TODO: + Q_EMIT wc->titleChanged(); } JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/) diff --git a/src/webview/qwebview_android_p.h b/src/webview/qwebview_android_p.h index 495c071..751b44f 100644 --- a/src/webview/qwebview_android_p.h +++ b/src/webview/qwebview_android_p.h @@ -53,7 +53,7 @@ #include <QtGui/qwindow.h> #include <QtCore/private/qjni_p.h> -#include "qwebview_p.h" +#include "qwebview_p_p.h" QT_BEGIN_NAMESPACE @@ -61,27 +61,35 @@ class QAndroidWebViewPrivate : public QWebViewPrivate { Q_OBJECT public: - QAndroidWebViewPrivate(QWebView *q); - virtual ~QAndroidWebViewPrivate(); + explicit QAndroidWebViewPrivate(QObject *p = 0); + ~QAndroidWebViewPrivate() Q_DECL_OVERRIDE; - QString getUrl() const; - bool canGoBack() const; - bool canGoForward() const; - QString getTitle() const; + QUrl url() const Q_DECL_OVERRIDE; + void setUrl(const QUrl &url) Q_DECL_OVERRIDE; + bool canGoBack() const Q_DECL_OVERRIDE; + bool canGoForward() const Q_DECL_OVERRIDE; + QString title() const Q_DECL_OVERRIDE; + int loadProgress() const Q_DECL_OVERRIDE; + bool isLoading() const Q_DECL_OVERRIDE; - void *nativeWebView() const; + void setParentView(QObject *view) Q_DECL_OVERRIDE; + void setGeometry(const QRect &geometry) Q_DECL_OVERRIDE; + void setVisibility(QWindow::Visibility visibility) Q_DECL_OVERRIDE; + void setVisible(bool visible) Q_DECL_OVERRIDE; public Q_SLOTS: - void loadUrl(const QString &url); - void goBack() const; - void goForward() const; - void stopLoading() const; + void goBack() Q_DECL_OVERRIDE; + void goForward() Q_DECL_OVERRIDE; + void reload() Q_DECL_OVERRIDE; + void stop() Q_DECL_OVERRIDE; private Q_SLOTS: void onApplicationStateChanged(Qt::ApplicationState state); private: quintptr m_id; + quint64 m_callbackId; + QWindow *m_window; QJNIObjectPrivate m_viewController; QJNIObjectPrivate m_webView; }; diff --git a/src/webview/qwebview_default.cpp b/src/webview/qwebview_default.cpp index b2517e6..cc19eda 100644 --- a/src/webview/qwebview_default.cpp +++ b/src/webview/qwebview_default.cpp @@ -63,6 +63,12 @@ void QDefaultWebViewPrivate::loadUrl(const QString &url) Q_UNUSED(url); } +void QDefaultWebViewPrivate::loadHtml(const QString &html, const QUrl &baseUrl) +{ + Q_UNUSED(html); + Q_UNUSED(baseUrl); +} + bool QDefaultWebViewPrivate::canGoBack() const { return false; diff --git a/src/webview/qwebview_ios.mm b/src/webview/qwebview_ios.mm index 93a775a..faa82c3 100644 --- a/src/webview/qwebview_ios.mm +++ b/src/webview/qwebview_ios.mm @@ -34,8 +34,8 @@ ** ****************************************************************************/ -#include "qwebview_p.h" #include "qwebview_ios_p.h" +#include "qwebview_p.h" #include <QtQuick/qquickitem.h> #include <QtCore/qmap.h> @@ -43,14 +43,81 @@ #include <CoreFoundation/CoreFoundation.h> #include <UIKit/UIKit.h> +#import <UIKit/UIView.h> +#import <UIKit/UIWindow.h> +#import <UIKit/UIViewController.h> +#import <UIKit/UITapGestureRecognizer.h> +#import <UIKit/UIGestureRecognizerSubclass.h> + QT_BEGIN_NAMESPACE -class QWebViewPrivate; +QWebViewPrivate *QWebViewPrivate::create(QWebView *q) +{ + return new QIosWebViewPrivate(q); +} + +static inline CGRect toCGRect(const QRectF &rect) +{ + return CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()); +} + +// ------------------------------------------------------------------------- + +@interface QIOSNativeViewSelectedRecognizer : UIGestureRecognizer <UIGestureRecognizerDelegate> +{ +@public + QNativeViewController *m_item; +} +@end + +@implementation QIOSNativeViewSelectedRecognizer + +- (id)initWithQWindowControllerItem:(QNativeViewController *)item +{ + self = [super initWithTarget:self action:@selector(nativeViewSelected:)]; + if (self) { + self.cancelsTouchesInView = NO; + self.delaysTouchesEnded = NO; + m_item = item; + } + return self; +} + +- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)other +{ + Q_UNUSED(other); + return NO; +} + +- (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)other +{ + Q_UNUSED(other); + return NO; +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + Q_UNUSED(touches); + Q_UNUSED(event); + self.state = UIGestureRecognizerStateRecognized; +} + +- (void)nativeViewSelected:(UIGestureRecognizer *)gestureRecognizer +{ + Q_UNUSED(gestureRecognizer); + m_item->setFocus(true); +} + +@end + +// ------------------------------------------------------------------------- + +class QWebViewInterface; @interface QtWebViewDelegate : NSObject<UIWebViewDelegate> { - QIOSWebViewPrivate *qIosWebViewPrivate; + QIosWebViewPrivate *qIosWebViewPrivate; } -- (QtWebViewDelegate *)initWithQWebViewPrivate:(QIOSWebViewPrivate *)webViewPrivate; +- (QtWebViewDelegate *)initWithQAbstractWebView:(QIosWebViewPrivate *)webViewPrivate; - (void)pageDone; // protocol: @@ -60,7 +127,7 @@ class QWebViewPrivate; @end @implementation QtWebViewDelegate -- (QtWebViewDelegate *)initWithQWebViewPrivate:(QIOSWebViewPrivate *)webViewPrivate +- (QtWebViewDelegate *)initWithQAbstractWebView:(QIosWebViewPrivate *)webViewPrivate { qIosWebViewPrivate = webViewPrivate; return self; @@ -68,10 +135,10 @@ class QWebViewPrivate; - (void)pageDone { - Q_EMIT qIosWebViewPrivate->progressChanged(100); - Q_EMIT qIosWebViewPrivate->pageFinished(qIosWebViewPrivate->requestUrl); - Q_EMIT qIosWebViewPrivate->titleChanged(qIosWebViewPrivate->getTitle()); - // QWebViewPrivate emits urlChanged. + Q_EMIT qIosWebViewPrivate->loadProgressChanged(); + Q_EMIT qIosWebViewPrivate->loadingChanged(); + Q_EMIT qIosWebViewPrivate->titleChanged(); + Q_EMIT qIosWebViewPrivate->urlChanged(); } - (void)webViewDidStartLoad:(UIWebView *)webView @@ -81,7 +148,8 @@ class QWebViewPrivate; // should provide per-page notifications. Keep track of started frame loads // and emit notifications when the final frame completes. ++qIosWebViewPrivate->requestFrameCount; - emit qIosWebViewPrivate->pageStarted(qIosWebViewPrivate->requestUrl); + Q_EMIT qIosWebViewPrivate->loadingChanged(); + Q_EMIT qIosWebViewPrivate->loadProgressChanged(); } - (void)webViewDidFinishLoad:(UIWebView *)webView @@ -100,77 +168,119 @@ class QWebViewPrivate; } @end -QWebViewPrivate *QWebViewPrivate::create(QWebView *q) -{ - QIOSWebViewPrivate *result = new QIOSWebViewPrivate(q); - result->ensureNativeWebView(); - return result; -} - -QIOSWebViewPrivate::QIOSWebViewPrivate(QWebView *q) - : QWebViewPrivate(q) +QIosWebViewPrivate::QIosWebViewPrivate(QObject *p) + : QWebViewPrivate(p) + , uiWebView(0) + , m_recognizer(0) { CGRect frame = CGRectMake(0.0, 0.0, 400, 400); - UIWebView *webView = [[UIWebView alloc] initWithFrame:frame]; - webView.delegate = [[QtWebViewDelegate alloc] initWithQWebViewPrivate:this]; - uiWebView = webView; + uiWebView = [[UIWebView alloc] initWithFrame:frame]; + uiWebView.delegate = [[QtWebViewDelegate alloc] initWithQAbstractWebView:this]; + + m_recognizer = [[QIOSNativeViewSelectedRecognizer alloc] initWithQWindowControllerItem:this]; + [uiWebView addGestureRecognizer:m_recognizer]; + } -QIOSWebViewPrivate::~QIOSWebViewPrivate() +QIosWebViewPrivate::~QIosWebViewPrivate() { [uiWebView.delegate release]; uiWebView.delegate = nil; // reset as per UIWebViewDelegate documentation [uiWebView release]; + [m_recognizer release]; } -QString QIOSWebViewPrivate::getUrl() const +QUrl QIosWebViewPrivate::url() const { NSString *currentURL = [uiWebView stringByEvaluatingJavaScriptFromString:@"window.location.href"]; return QString::fromNSString(currentURL); } -void QIOSWebViewPrivate::loadUrl(const QString &url) +void QIosWebViewPrivate::setUrl(const QUrl &url) { - Q_EMIT progressChanged(0); - requestUrl = url; requestFrameCount = 0; - [uiWebView loadRequest:[NSURLRequest requestWithURL:QUrl(url).toNSURL()]]; + [uiWebView loadRequest:[NSURLRequest requestWithURL:url.toNSURL()]]; } -bool QIOSWebViewPrivate::canGoBack() const +bool QIosWebViewPrivate::canGoBack() const { return uiWebView.canGoBack; } -void QIOSWebViewPrivate::goBack() const +bool QIosWebViewPrivate::canGoForward() const { - [uiWebView goBack]; + return uiWebView.canGoForward; } -bool QIOSWebViewPrivate::canGoForward() const +QString QIosWebViewPrivate::title() const { - return uiWebView.canGoForward; + NSString *title = [uiWebView stringByEvaluatingJavaScriptFromString:@"document.title"]; + return QString::fromNSString(title); } -void QIOSWebViewPrivate::goForward() const +int QIosWebViewPrivate::loadProgress() const { - [uiWebView goForward]; + // TODO: + return isLoading() ? 100 : 0; } -QString QIOSWebViewPrivate::getTitle() const +bool QIosWebViewPrivate::isLoading() const { - NSString *title = [uiWebView stringByEvaluatingJavaScriptFromString:@"document.title"]; - return QString::fromNSString(title); + return uiWebView.loading; +} + +void QIosWebViewPrivate::setParentView(QObject *view) +{ + if (!uiWebView) + return; + + QWindow *window = qobject_cast<QWindow *>(view); + if (window != 0) { + UIView *parentView = reinterpret_cast<UIView *>(window->winId()); + [parentView addSubview:uiWebView]; + } else { + [uiWebView removeFromSuperview]; + } +} + +void QIosWebViewPrivate::setGeometry(const QRect &geometry) +{ + [uiWebView setFrame:toCGRect(geometry)]; +} + +void QIosWebViewPrivate::setVisibility(QWindow::Visibility visibility) +{ + Q_UNUSED(visibility); +} + +void QIosWebViewPrivate::setVisible(bool visible) +{ + [uiWebView setHidden:visible]; +} + +void QIosWebViewPrivate::setFocus(bool focus) +{ + Q_EMIT requestFocus(focus); +} + +void QIosWebViewPrivate::goBack() +{ + [uiWebView goBack]; +} + +void QIosWebViewPrivate::goForward() +{ + [uiWebView goForward]; } -void QIOSWebViewPrivate::stopLoading() const +void QIosWebViewPrivate::stop() { [uiWebView stopLoading]; } -void *QIOSWebViewPrivate::nativeWebView() const +void QIosWebViewPrivate::reload() { - return uiWebView; + [uiWebView reload]; } QT_END_NAMESPACE diff --git a/src/webview/qwebview_ios_p.h b/src/webview/qwebview_ios_p.h index b7cbbf2..774d707 100644 --- a/src/webview/qwebview_ios_p.h +++ b/src/webview/qwebview_ios_p.h @@ -52,34 +52,43 @@ #include <QtCore/qurl.h> #include <QtGui/qwindow.h> -#include "qwebview_p.h" +#include "qwebview_p_p.h" QT_BEGIN_NAMESPACE Q_FORWARD_DECLARE_OBJC_CLASS(UIWebView); +Q_FORWARD_DECLARE_OBJC_CLASS(UIGestureRecognizer); -class QIOSWebViewPrivate : public QWebViewPrivate +class QIosWebViewPrivate : public QWebViewPrivate { Q_OBJECT public: - QIOSWebViewPrivate(QWebView *q); - virtual ~QIOSWebViewPrivate(); + explicit QIosWebViewPrivate(QObject *p = 0); + ~QIosWebViewPrivate() Q_DECL_OVERRIDE; - QString getUrl() const; - bool canGoBack() const; - bool canGoForward() const; - QString getTitle() const; + QUrl url() const Q_DECL_OVERRIDE; + void setUrl(const QUrl &url) Q_DECL_OVERRIDE; + bool canGoBack() const Q_DECL_OVERRIDE; + bool canGoForward() const Q_DECL_OVERRIDE; + QString title() const Q_DECL_OVERRIDE; + int loadProgress() const Q_DECL_OVERRIDE; + bool isLoading() const Q_DECL_OVERRIDE; - void *nativeWebView() const; + void setParentView(QObject *view) Q_DECL_OVERRIDE; + void setGeometry(const QRect &geometry) Q_DECL_OVERRIDE; + void setVisibility(QWindow::Visibility visibility) Q_DECL_OVERRIDE; + void setVisible(bool visible) Q_DECL_OVERRIDE; + void setFocus(bool focus) Q_DECL_OVERRIDE; public Q_SLOTS: - void loadUrl(const QString &url); - void goBack() const; - void goForward() const; - void stopLoading() const; + void goBack() Q_DECL_OVERRIDE; + void goForward() Q_DECL_OVERRIDE; + void reload() Q_DECL_OVERRIDE; + void stop() Q_DECL_OVERRIDE; + public: UIWebView *uiWebView; - QString requestUrl; + UIGestureRecognizer *m_recognizer; int requestFrameCount; }; diff --git a/src/webview/qwebview_p.h b/src/webview/qwebview_p.h index fdf08a3..2a92620 100644 --- a/src/webview/qwebview_p.h +++ b/src/webview/qwebview_p.h @@ -34,8 +34,8 @@ ** ****************************************************************************/ -#ifndef QWEBVIEW_H -#define QWEBVIEW_H +#ifndef QWEBVIEW_P_H +#define QWEBVIEW_P_H // // W A R N I N G @@ -48,124 +48,63 @@ // We mean it. // -#include <QtWebView/qwebview_global.h> - -#if !defined(QT_WEBVIEW_WEBENGINE_BACKEND) - -#include "qwindowcontrolleritem_p.h" +#include "qwebview_p_p.h" +#include "qwebviewinterface_p.h" +#include "qnativeviewcontroller_p.h" #include <QtCore/qobject.h> #include <QtCore/qurl.h> #include <QtGui/qimage.h> - +#include <QtQml/qjsvalue.h> QT_BEGIN_NAMESPACE -class QWebView; -class QWebViewPrivate : public QObject -{ - Q_OBJECT -public: - QWebViewPrivate(QWebView *q); - ~QWebViewPrivate(); - - virtual QString getUrl() const = 0; - virtual bool canGoBack() const = 0; - virtual bool canGoForward() const = 0; - virtual QString getTitle() const = 0; - virtual void *nativeWebView() const = 0; - - static QWebViewPrivate *create(QWebView *q); - -public Q_SLOTS: - virtual void loadUrl(const QString &url) = 0; - virtual void goBack() const = 0; - virtual void goForward() const = 0; - virtual void stopLoading() const = 0; - -private Q_SLOTS: - void onPageStartedPrivate(QString url); - void onPageFinishedPrivate(QString url); - void onTitleChangedPrivate(QString title); - void onProgressChangedPrivate(int progress); - -Q_SIGNALS: - void pageStarted(QString url); - void pageFinished(QString url); - void progressChanged(int progress); - void titleChanged(QString title); - -protected: - Q_DECLARE_PUBLIC(QWebView) - void ensureNativeWebView(); - -private: - int m_loadProgress; - bool m_loading; - QString m_title; - QUrl m_url; - QWebView *q_ptr; -}; - -class Q_WEBVIEW_EXPORT QWebView : public QWindowControllerItem +class Q_WEBVIEW_EXPORT QWebView + : public QObject + , public QWebViewInterface + , public QNativeViewController { Q_OBJECT - Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged) - Q_PROPERTY(bool loading READ isLoading NOTIFY loadingChanged) - Q_PROPERTY(int loadProgress READ loadProgress NOTIFY loadProgressChanged) - Q_PROPERTY(QString title READ title NOTIFY titleChanged) - Q_PROPERTY(bool canGoBack READ canGoBack NOTIFY loadingChanged) - Q_PROPERTY(bool canGoForward READ canGoForward NOTIFY loadingChanged) - public: - QWebView(QQuickItem *parent = 0); - ~QWebView(); - - QUrl url() const; - void setUrl(const QUrl &url); - int loadProgress() const; - QString title() const; - bool canGoBack() const; - bool isLoading() const; - bool canGoForward() const; + explicit QWebView(QObject *p = 0); + ~QWebView() Q_DECL_OVERRIDE; + + QUrl url() const Q_DECL_OVERRIDE; + void setUrl(const QUrl &url) Q_DECL_OVERRIDE; + bool canGoBack() const Q_DECL_OVERRIDE; + bool canGoForward() const Q_DECL_OVERRIDE; + QString title() const Q_DECL_OVERRIDE; + int loadProgress() const Q_DECL_OVERRIDE; + bool isLoading() const Q_DECL_OVERRIDE; + + void setParentView(QObject *view) Q_DECL_OVERRIDE; + void setGeometry(const QRect &geometry) Q_DECL_OVERRIDE; + void setVisibility(QWindow::Visibility visibility) Q_DECL_OVERRIDE; + void setVisible(bool visible) Q_DECL_OVERRIDE; + void setFocus(bool focus) Q_DECL_OVERRIDE; public Q_SLOTS: - void goBack(); - void goForward(); - void reload(); - void stop(); + void goBack() Q_DECL_OVERRIDE; + void goForward() Q_DECL_OVERRIDE; + void reload() Q_DECL_OVERRIDE; + void stop() Q_DECL_OVERRIDE; Q_SIGNALS: void titleChanged(); void urlChanged(); void loadingChanged(); void loadProgressChanged(); + void requestFocus(bool focus); protected: - void componentComplete() Q_DECL_OVERRIDE; + void init(); private: - void load(const QUrl &url); - + friend class QQuickViewController; + friend class QQuickWebView; Q_DECLARE_PRIVATE(QWebView) QScopedPointer<QWebViewPrivate> d_ptr; }; QT_END_NAMESPACE -#else - -# include <QtWebEngine/private/qquickwebengineview_p.h> - -QT_BEGIN_NAMESPACE - -class Q_WEBVIEW_EXPORT QWebView : public QQuickWebEngineView -{ - Q_OBJECT -}; - -QT_END_NAMESPACE - -#endif - - -#endif +#endif // QWEBVIEW_P_H diff --git a/src/webview/qwebview_p_p.h b/src/webview/qwebview_p_p.h new file mode 100644 index 0000000..e0b8431 --- /dev/null +++ b/src/webview/qwebview_p_p.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebView 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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWEBVIEW_P_P_H +#define QWEBVIEW_P_P_H + +#include "qwebviewinterface_p.h" +#include "qnativeviewcontroller_p.h" + +QT_BEGIN_NAMESPACE + +class QWebView; + +class Q_WEBVIEW_EXPORT QWebViewPrivate + : public QObject + , public QWebViewInterface + , public QNativeViewController +{ + Q_OBJECT +public: + static QWebViewPrivate *create(QWebView *q); + +Q_SIGNALS: + void titleChanged(); + void urlChanged(); + void loadingChanged(); + void loadProgressChanged(); + void javaScriptResult(int id, const QVariant &result); + void requestFocus(bool focus); + +protected: + explicit QWebViewPrivate(QObject *p = 0) : QObject(p) { } +}; + +QT_END_NAMESPACE + +#endif // QWEBVIEW_P_P_H + diff --git a/src/webview/qwebview_default_p.h b/src/webview/qwebviewinterface_p.h index 9231e4e..86d370c 100644 --- a/src/webview/qwebview_default_p.h +++ b/src/webview/qwebviewinterface_p.h @@ -1,9 +1,6 @@ -#ifndef QWEBVIEW_DEFAULT_P_H -#define QWEBVIEW_DEFAULT_P_H - /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtWebView module of the Qt Toolkit. @@ -37,6 +34,9 @@ ** ****************************************************************************/ +#ifndef QWEBVIEWINTERFACE_H +#define QWEBVIEWINTERFACE_H + // // W A R N I N G // ------------- @@ -48,31 +48,34 @@ // We mean it. // -#include "qwebview_p.h" +#include <QtWebView/qwebview_global.h> + +#include <QtCore/qobject.h> +#include <QtCore/qurl.h> +#include <QtGui/qimage.h> + QT_BEGIN_NAMESPACE -class QDefaultWebViewPrivate : public QWebViewPrivate +class QJSValue; + +class QWebViewInterface { - Q_OBJECT public: - QDefaultWebViewPrivate(QWebView *q); - ~QDefaultWebViewPrivate(); - - QString getUrl() const; - bool canGoBack() const; - bool canGoForward() const; - QString getTitle() const; + virtual ~QWebViewInterface() {} + virtual QUrl url() const = 0; + virtual void setUrl(const QUrl &url) = 0; + virtual bool canGoBack() const = 0; + virtual bool canGoForward() const = 0; + virtual QString title() const = 0; + virtual int loadProgress() const = 0; + virtual bool isLoading() const = 0; - void *nativeWebView() const; - -public Q_SLOTS: - void loadUrl(const QString &url); - void goBack() const; - void goForward() const; - void stopLoading() const; + // Q_SLOTS + virtual void goBack() = 0; + virtual void goForward() = 0; + virtual void stop() = 0; + virtual void reload() = 0; }; -QT_END_NAMESPACE - -#endif // QWEBVIEW_DEFAULT_P_H +#endif // QWEBVIEWINTERFACE_H diff --git a/src/webview/qwindowcontrolleritem_ios.mm b/src/webview/qwindowcontrolleritem_ios.mm deleted file mode 100644 index 6127792..0000000 --- a/src/webview/qwindowcontrolleritem_ios.mm +++ /dev/null @@ -1,152 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtWebView 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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later 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 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwindowcontrolleritem_p.h" - -#include <QtGui/QWindow> -#include <QtQuick/QQuickWindow> - -#import <UIKit/UIView.h> -#import <UIKit/UIWindow.h> -#import <UIKit/UIViewController.h> -#import <UIKit/UITapGestureRecognizer.h> -#import <UIKit/UIGestureRecognizerSubclass.h> - -static inline CGRect toCGRect(const QRectF &rect) -{ - return CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()); -} - -// ------------------------------------------------------------------------- - -@interface QIOSNativeViewSelectedRecognizer : UIGestureRecognizer <UIGestureRecognizerDelegate> -{ -@public - QWindowControllerItem *m_item; -} -@end - -@implementation QIOSNativeViewSelectedRecognizer - -- (id)initWithQWindowControllerItem:(QWindowControllerItem *)item -{ - self = [super initWithTarget:self action:@selector(nativeViewSelected:)]; - if (self) { - self.cancelsTouchesInView = NO; - self.delaysTouchesEnded = NO; - m_item = item; - } - return self; -} - -- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)other -{ - Q_UNUSED(other); - return NO; -} - -- (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)other -{ - Q_UNUSED(other); - return NO; -} - -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event -{ - Q_UNUSED(touches); - Q_UNUSED(event); - self.state = UIGestureRecognizerStateRecognized; -} - -- (void)nativeViewSelected:(UIGestureRecognizer *)gestureRecognizer -{ - Q_UNUSED(gestureRecognizer); - m_item->setFocus(true); -} - -@end - -// ------------------------------------------------------------------------- - -QWindowControllerItem::QWindowControllerItem(QQuickItem *parent) - : QQuickItem(parent) - , m_controlledUIView(0) -{ - connect(this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(onWindowChanged(QQuickWindow*))); - connect(this, SIGNAL(visibleChanged()), this, SLOT(onVisibleChanged())); -} - -QWindowControllerItem::~QWindowControllerItem() -{ - [m_recognizer release]; - [m_controlledUIView release]; -} - -void QWindowControllerItem::setNativeWindow(WId windowId) -{ - m_controlledUIView = [reinterpret_cast<UIView *>(windowId) retain]; - m_recognizer = [[QIOSNativeViewSelectedRecognizer alloc] initWithQWindowControllerItem:this]; - [m_controlledUIView addGestureRecognizer:m_recognizer]; -} - -void QWindowControllerItem::componentComplete() -{ - QQuickItem::componentComplete(); -} - -void QWindowControllerItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) -{ - QQuickItem::geometryChanged(newGeometry, oldGeometry); - [m_controlledUIView setFrame:toCGRect(mapRectToScene(newGeometry).toRect())]; -} - -void QWindowControllerItem::onWindowChanged(QQuickWindow* window) -{ - if (!m_controlledUIView) - return; - - if (window != 0) { - UIView *parentView = reinterpret_cast<UIView *>(window->winId()); - [parentView addSubview:m_controlledUIView]; - } else { - [m_controlledUIView removeFromSuperview]; - } -} - -void QWindowControllerItem::onVisibleChanged() -{ - [m_controlledUIView setHidden:isVisible()]; -} diff --git a/src/webview/webview-lib.pri b/src/webview/webview-lib.pri index 86d0678..653e2e9 100644 --- a/src/webview/webview-lib.pri +++ b/src/webview/webview-lib.pri @@ -8,29 +8,37 @@ INCLUDEPATH += $$PWD PUBLIC_HEADERS += \ qwebview_global.h -PRIVATE_HEADERS += \ - qwebview_p.h +COMMON_HEADERS += \ + qwebview_p.h \ + qwebviewinterface_p.h \ + qquickwebview.h \ + qnativeviewcontroller_p.h \ + qwebview_p_p.h \ + qquickviewcontroller_p.h + +COMMON_SOURCES += \ + qwebview.cpp \ + qquickwebview.cpp \ + qquickviewcontroller.cpp android { QT += core-private LIBS += -ljnigraphics SOURCES += \ - qwebview_android.cpp \ - qwebview.cpp \ - qwindowcontrolleritem.cpp + $$COMMON_SOURCES \ + qwebview_android.cpp PRIVATE_HEADERS += \ - qwebview_android_p.h \ - qwindowcontrolleritem_p.h + $$COMMON_HEADERS \ + qwebview_android_p.h } else:ios { SOURCES += \ - qwebview.cpp + $$COMMON_SOURCES OBJECTIVE_SOURCES += \ - qwebview_ios.mm \ - qwindowcontrolleritem_ios.mm + qwebview_ios.mm PRIVATE_HEADERS += \ - qwebview_ios_p.h \ - qwindowcontrolleritem_p.h + $$COMMON_HEADERS \ + qwebview_ios_p.h } else { qtHaveModule(webengine) { @@ -38,12 +46,9 @@ android { DEFINES += QT_WEBVIEW_WEBENGINE_BACKEND } else { SOURCES += \ - qwebview_default.cpp \ - qwebview.cpp \ - qwindowcontrolleritem.cpp + qwebview.cpp PRIVATE_HEADERS += \ - qwebview_default_p.h \ - qwindowcontrolleritem_p.h + qwebviewinterface_p.h } } |