From 8e8cd9ea03dbdfab4d1707ca751b72dd6ac3c178 Mon Sep 17 00:00:00 2001 From: Kirill Burtsev Date: Tue, 19 Mar 2019 10:15:07 +0100 Subject: Web Notifications widgets' API example Change-Id: If6aba0e9da1ece59c91be03ae2f56513e758f5e5 Reviewed-by: Kai Koehne Reviewed-by: Leena Miettinen --- .../webenginewidgets/notifications/data/data.qrc | 6 + .../webenginewidgets/notifications/data/icon.png | Bin 0 -> 2252 bytes .../webenginewidgets/notifications/data/index.html | 90 ++++++++++++ .../doc/images/notifications-example.png | Bin 0 -> 14732 bytes .../notifications/doc/src/notifications.qdoc | 156 +++++++++++++++++++++ examples/webenginewidgets/notifications/main.cpp | 100 +++++++++++++ .../notifications/notificationpopup.h | 132 +++++++++++++++++ .../notifications/notifications.pro | 10 ++ examples/webenginewidgets/webenginewidgets.pro | 1 + 9 files changed, 495 insertions(+) create mode 100644 examples/webenginewidgets/notifications/data/data.qrc create mode 100644 examples/webenginewidgets/notifications/data/icon.png create mode 100644 examples/webenginewidgets/notifications/data/index.html create mode 100644 examples/webenginewidgets/notifications/doc/images/notifications-example.png create mode 100644 examples/webenginewidgets/notifications/doc/src/notifications.qdoc create mode 100644 examples/webenginewidgets/notifications/main.cpp create mode 100644 examples/webenginewidgets/notifications/notificationpopup.h create mode 100644 examples/webenginewidgets/notifications/notifications.pro (limited to 'examples') 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 @@ + + + index.html + icon.png + + diff --git a/examples/webenginewidgets/notifications/data/icon.png b/examples/webenginewidgets/notifications/data/icon.png new file mode 100644 index 000000000..4c3870c06 Binary files /dev/null and b/examples/webenginewidgets/notifications/data/icon.png 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 @@ + + + +Web Notifications Example + + + +

Click the button to send a notification

+ + + +

+ + +


+ +

+ + + +


+ +

More info can be found on:

+ + + 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 Binary files /dev/null and b/examples/webenginewidgets/notifications/doc/images/notifications-example.png 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 +#include +#include +#include +#include + +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 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 +#include +#include +#include +#include +#include +#include +#include + +#include + +class NotificationPopup : public QWidget { + Q_OBJECT + + QLabel m_icon, m_title, m_message; + std::unique_ptr 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 &newNotification) { + if (notification) { + notification->close(); + notification.reset(); + } + + notification.swap(newNotification); + + m_title.setText("" + notification->title() + ""); + 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 \ -- cgit v1.2.3