summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorKirill Burtsev <kirill.burtsev@qt.io>2019-03-19 10:15:07 +0100
committerKirill Burtsev <kirill.burtsev@qt.io>2019-05-20 13:50:39 +0200
commit8e8cd9ea03dbdfab4d1707ca751b72dd6ac3c178 (patch)
treeb99e1135cca621c42a5ff8e4e298c48122526e3b /examples
parent819aa370ec413ba1ea4506d591d4debe87c21831 (diff)
Web Notifications widgets' API example
Change-Id: If6aba0e9da1ece59c91be03ae2f56513e758f5e5 Reviewed-by: Kai Koehne <kai.koehne@qt.io> Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
Diffstat (limited to 'examples')
-rw-r--r--examples/webenginewidgets/notifications/data/data.qrc6
-rw-r--r--examples/webenginewidgets/notifications/data/icon.pngbin0 -> 2252 bytes
-rw-r--r--examples/webenginewidgets/notifications/data/index.html90
-rw-r--r--examples/webenginewidgets/notifications/doc/images/notifications-example.pngbin0 -> 14732 bytes
-rw-r--r--examples/webenginewidgets/notifications/doc/src/notifications.qdoc156
-rw-r--r--examples/webenginewidgets/notifications/main.cpp100
-rw-r--r--examples/webenginewidgets/notifications/notificationpopup.h132
-rw-r--r--examples/webenginewidgets/notifications/notifications.pro10
-rw-r--r--examples/webenginewidgets/webenginewidgets.pro1
9 files changed, 495 insertions, 0 deletions
diff --git a/examples/webenginewidgets/notifications/data/data.qrc b/examples/webenginewidgets/notifications/data/data.qrc
new file mode 100644
index 000000000..bc252b89c
--- /dev/null
+++ b/examples/webenginewidgets/notifications/data/data.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/">
+ <file>index.html</file>
+ <file>icon.png</file>
+ </qresource>
+</RCC>
diff --git a/examples/webenginewidgets/notifications/data/icon.png b/examples/webenginewidgets/notifications/data/icon.png
new file mode 100644
index 000000000..4c3870c06
--- /dev/null
+++ b/examples/webenginewidgets/notifications/data/icon.png
Binary files differ
diff --git a/examples/webenginewidgets/notifications/data/index.html b/examples/webenginewidgets/notifications/data/index.html
new file mode 100644
index 000000000..ebb73b573
--- /dev/null
+++ b/examples/webenginewidgets/notifications/data/index.html
@@ -0,0 +1,90 @@
+<!doctype html>
+<html>
+<head>
+<title>Web Notifications Example</title>
+<script>
+ var notificationsCreated = 0
+
+ function getPermission() { return document.Notification }
+ function resetPermission(permission = 'default') {
+ document.Notification = permission
+ document.getElementById('state').value = getPermission()
+ }
+
+ function createNotification() {
+ let title = 'Notification #' + ++notificationsCreated
+ let options = { body: 'Visit doc.qt.io for more info!', icon: 'icon.png', }
+
+ let notification = new Notification(title, options)
+ document.notification = notification
+
+ notification.onerror = function(error) {
+ document.getElementById('act').value += ' with error'
+ document.notification = null
+ }
+ notification.onshow = function() {
+ document.getElementById('act').value += ', shown'
+ document.getElementById('close').style.display = 'inline'
+ }
+ notification.onclick = function() {
+ document.getElementById('act').value += ', clicked'
+ }
+ notification.onclose = function() {
+ if (document.notification && notification == document.notification) {
+ document.getElementById('act').value += ' and closed'
+ document.getElementById('close').style.display = 'none'
+ document.notification = null
+ }
+ }
+
+ console.log('...notification created [Title: ' + title + ']')
+ document.getElementById('act').value = 'Notification was created'
+ }
+
+ function onMakeNotification() {
+ if (getPermission() == 'granted') {
+ createNotification()
+ } else if (getPermission() == 'denied') {
+ setTimeout(function() {
+ if (window.confirm('Notifications are disabled!\n' +
+ 'Permission needs to be granted by user. Reset?'))
+ resetPermission()
+ }, 1)
+ } else {
+ Notification.requestPermission().then(function (permission) {
+ console.info('notifications request: ' + permission)
+ resetPermission(permission)
+ if (permission == 'granted')
+ createNotification()
+ })
+ }
+ }
+
+ function closeNotification() { if (document.notification) document.notification.close() }
+
+ document.addEventListener('DOMContentLoaded', function() { resetPermission(Notification.permission) })
+</script>
+</head>
+<body style='text-align:center;'>
+ <h3>Click the button to send a notification</h3>
+
+ <button onclick='onMakeNotification()'>Notify!</button>
+
+ <p>
+ <output id='act'></output>
+ <button id='close' style='display: none;' onclick='closeNotification()'>Close</button>
+ </p><br>
+
+ <p>
+ <label for='state'>Permission:</label>
+ <output id='state'></output>
+ <button onclick='resetPermission()'>Reset</button>
+ </p><br>
+
+ <h4>More info can be found on:</h4>
+ <ul style='list-style-type: none;'>
+ <li>W3 <a href='https://www.w3.org/TR/notifications'>Web Notifications</a> standard</li>
+ <li>Documentation for <a href='https://doc.qt.io'>Qt WebEngine</a> module</li>
+ </ul>
+</body>
+</html>
diff --git a/examples/webenginewidgets/notifications/doc/images/notifications-example.png b/examples/webenginewidgets/notifications/doc/images/notifications-example.png
new file mode 100644
index 000000000..671cd1703
--- /dev/null
+++ b/examples/webenginewidgets/notifications/doc/images/notifications-example.png
Binary files differ
diff --git a/examples/webenginewidgets/notifications/doc/src/notifications.qdoc b/examples/webenginewidgets/notifications/doc/src/notifications.qdoc
new file mode 100644
index 000000000..2c999e7e1
--- /dev/null
+++ b/examples/webenginewidgets/notifications/doc/src/notifications.qdoc
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example webenginewidgets/notifications
+ \title WebEngine Notifications Example
+ \ingroup webengine-widgetexamples
+ \brief Demonstrates how to pass HTML5 web notifications to users.
+
+ \image notifications-example.png
+
+ \e {\WebEngine Notifications} demonstrates how to use the
+ \l QWebEngineProfile::setNotificationPresenter() method and
+ \l QWebEngineNotification class to show an HTML5 web
+ notification to the user.
+
+ \include examples-run.qdocinc
+
+ \section1 HTML Page
+
+ In this example, we create an internal HTML page that is added through
+ a resource collection file (.qrc). The page displays buttons for requesting
+ permissions and creating a notification. In addition, it contains JavaScript
+ logic for triggering these actions.
+
+ \quotefromfile webenginewidgets/notifications/data/index.html
+ \skipto Notification.requestPermission
+ \printline requestPermission
+ \dots
+ \skipto if
+ \printuntil createNotification()
+ \printline /^})$/
+
+ \quotefromfile webenginewidgets/notifications/data/index.html
+ \skipto createNotification()
+ \printuntil Notification
+ \dots
+ \printline /^})$/
+
+ \section1 Main Function
+
+ In the \c main function, we instantiate a QWebEngineView, load our internal
+ HTML page, and set up the required callbacks for notifications handling.
+
+ \section2 Requesting Feature Permissions
+
+ We then use the \l QWebEnginePage::featurePermissionRequested() call to
+ request the user's permission to show notifications on their device.
+
+ \quotefromfile webenginewidgets/notifications/main.cpp
+ \skipto featurePermissionRequested
+ \printuntil });
+
+ \section2 Handling New Notifications
+
+ We then construct a \c NotificationPopup that encapsulates
+ the data of the HTML web notification. We also use the
+ \l QWebEngineProfile::setNotificationPresenter() call to set
+ our handler, which we use in conjunction with our \c popup
+ to handle all new notifications.
+
+ \skipto popup
+ \printuntil });
+
+ \section1 Presenting Notifications to Users
+
+ The \c NotificationPopup class in this example is a simple
+ QWidget-based class that uses multiple QLabel instances
+ for displaying the notification's title, message, and icon.
+
+ \quotefromfile webenginewidgets/notifications/notificationpopup.h
+ \skipto class NotificationPopup
+ \printto public:
+
+ \section2 Presenting Notifications
+
+ Inside the \c present method, we first close and release the previous
+ notification if we have one and then take ownership of a new notification
+ by calling the \c std::unique_ptr::swap method on our internal notification
+ instance.
+
+ \skipto present
+ \printto m_title
+
+ Then we query the notification instance for a title, a message,
+ and an icon by calling \l QWebEngineNotification::title(),
+ \l QWebEngineNotification::message(), \l QWebEngineNotification::icon()
+ and set up the appropriate labels in our popup.
+
+ \printuntil m_icon
+
+ After that we are ready to display our notification to the user
+ by calling the \l QWidget::show() method. On this step we also call the
+ \l QWebEngineNotification::show() method to notify \c JavaScript code
+ about our \e show event.
+
+ \printuntil notification->show
+
+ Finally, we set up a callback to handle the \e close event from the
+ \c JavaScript side by connecting to the \l QWebEngineNotification::closed()
+ signal. We also schedule a timer event to close our active notification
+ automatically.
+
+ \skipto QWebEngineNotification::closed
+ \printuntil QTimer
+ \printline /^\}/
+
+ \section2 Closing Active Notification
+
+ We execute the \e close step for the currently active notification either by
+ timeout or by handling the \c JavaScript event. First, we hide the popup
+ widget itself by calling \l QWidget::hide(). Then, we notify the \c JavaScript
+ code by calling the \l QWebEngineNotification::close() method. Finally, we
+ destroy the notification object through the \c std::unique_ptr::reset() method.
+
+ \skipto onClosed
+ \dots
+ \skipto hide()
+ \printuntil reset
+
+ \section2 Implementing User Interaction
+
+ To implement the \e click step for a notification, we handle mouse interaction
+ through \l QWidget::mouseReleaseEvent(). On this event, the \c JavaScript code
+ is notified by calling the \l QWebEngineNotification::click() method.
+ Then we automatically perform the \e close step as a notification is
+ considered fully handled and no longer needed, and therefore can be destroyed.
+
+ \skipto mouseReleaseEvent
+ \printuntil onClosed
+ \printuntil /^\}/
+*/
diff --git a/examples/webenginewidgets/notifications/main.cpp b/examples/webenginewidgets/notifications/main.cpp
new file mode 100644
index 000000000..661b82ff5
--- /dev/null
+++ b/examples/webenginewidgets/notifications/main.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "notificationpopup.h"
+
+#include <QApplication>
+#include <QDesktopServices>
+#include <QWebEnginePage>
+#include <QWebEngineProfile>
+#include <QWebEngineView>
+
+class WebEnginePage : public QWebEnginePage {
+public:
+ WebEnginePage(QWidget *parent) : QWebEnginePage(parent) { }
+
+ bool acceptNavigationRequest(const QUrl &url, NavigationType, bool) override {
+ if (url.scheme() != "https")
+ return true;
+ QDesktopServices::openUrl(url);
+ return false;
+ }
+};
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QCoreApplication::setOrganizationName("QtExamples");
+ QApplication app(argc, argv);
+
+ QWebEngineView view;
+
+ // set custom page to open all page's links for https scheme in system browser
+ view.setPage(new WebEnginePage(&view));
+
+ QObject::connect(view.page(), &QWebEnginePage::featurePermissionRequested,
+ [&] (const QUrl &origin, QWebEnginePage::Feature feature) {
+ if (feature != QWebEnginePage::Notifications)
+ return;
+ view.page()->setFeaturePermission(origin, feature, QWebEnginePage::PermissionGrantedByUser);
+ });
+
+ auto profile = view.page()->profile();
+ auto popup = new NotificationPopup(&view);
+ profile->setNotificationPresenter([&] (std::unique_ptr<QWebEngineNotification> notification) {
+ popup->present(notification);
+ });
+
+ view.resize(640, 480);
+ view.show();
+ view.setUrl(QStringLiteral("qrc:/index.html"));
+ return app.exec();
+}
+
diff --git a/examples/webenginewidgets/notifications/notificationpopup.h b/examples/webenginewidgets/notifications/notificationpopup.h
new file mode 100644
index 000000000..fcbb003b9
--- /dev/null
+++ b/examples/webenginewidgets/notifications/notificationpopup.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QMouseEvent>
+#include <QPushButton>
+#include <QSpacerItem>
+#include <QTimer>
+#include <QVBoxLayout>
+#include <QWebEngineNotification>
+
+#include <memory>
+
+class NotificationPopup : public QWidget {
+ Q_OBJECT
+
+ QLabel m_icon, m_title, m_message;
+ std::unique_ptr<QWebEngineNotification> notification;
+
+public:
+ NotificationPopup(QWidget *parent) : QWidget(parent) {
+ setWindowFlags(Qt::ToolTip);
+ auto rootLayout = new QHBoxLayout(this);
+
+ rootLayout->addWidget(&m_icon);
+
+ auto bodyLayout = new QVBoxLayout;
+ rootLayout->addLayout(bodyLayout);
+
+ auto titleLayout = new QHBoxLayout;
+ bodyLayout->addLayout(titleLayout);
+
+ titleLayout->addWidget(&m_title);
+ titleLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding));
+
+ auto close = new QPushButton(tr("Close"));
+ titleLayout->addWidget(close);
+ connect(close, &QPushButton::clicked, this, &NotificationPopup::onClosed);
+
+ bodyLayout->addWidget(&m_message);
+ adjustSize();
+ }
+
+ void present(std::unique_ptr<QWebEngineNotification> &newNotification) {
+ if (notification) {
+ notification->close();
+ notification.reset();
+ }
+
+ notification.swap(newNotification);
+
+ m_title.setText("<b>" + notification->title() + "</b>");
+ m_message.setText(notification->message());
+ m_icon.setPixmap(QPixmap::fromImage(notification->icon()).scaledToHeight(m_icon.height()));
+
+ show();
+ notification->show();
+
+ connect(notification.get(), &QWebEngineNotification::closed, this, &NotificationPopup::onClosed);
+ QTimer::singleShot(10000, notification.get(), [&] () { onClosed(); });
+
+ // position our popup in the right corner of its parent widget
+ move(parentWidget()->mapToGlobal(parentWidget()->rect().bottomRight() - QPoint(width() + 10, height() + 10)));
+ }
+
+protected slots:
+ void onClosed() {
+ hide();
+ notification->close();
+ notification.reset();
+ }
+
+protected:
+ void mouseReleaseEvent(QMouseEvent *event) override {
+ QWidget::mouseReleaseEvent(event);
+ if (notification && event->button() == Qt::LeftButton) {
+ notification->click();
+ onClosed();
+ }
+ }
+};
+
diff --git a/examples/webenginewidgets/notifications/notifications.pro b/examples/webenginewidgets/notifications/notifications.pro
new file mode 100644
index 000000000..6e276d405
--- /dev/null
+++ b/examples/webenginewidgets/notifications/notifications.pro
@@ -0,0 +1,10 @@
+QT += webenginewidgets
+
+HEADERS = notificationpopup.h
+
+SOURCES = main.cpp
+
+RESOURCES = data/data.qrc
+
+target.path = $$[QT_INSTALL_EXAMPLES]/webenginewidgets/notifications
+INSTALLS += target
diff --git a/examples/webenginewidgets/webenginewidgets.pro b/examples/webenginewidgets/webenginewidgets.pro
index 0d47aac80..deb42a8cd 100644
--- a/examples/webenginewidgets/webenginewidgets.pro
+++ b/examples/webenginewidgets/webenginewidgets.pro
@@ -7,6 +7,7 @@ SUBDIRS += \
minimal \
contentmanipulation \
cookiebrowser \
+ notifications \
simplebrowser \
stylesheetbrowser \
videoplayer \