feat: ISSUE #I62BVT 添加网页通知功能

WebEngineView 中添加 WebEngineView::present(std::unique_ptr<QWebEngineNotification> &newNotification) 函数,通过 DNotifySender 转发系统通知

Log: 添加网页通知功能,通知图片缓存在 /tmp 下;使用 DLogManager 生成日志;修复强制使用 DTK 平台插件异常问题
This commit is contained in:
zty199 2022-12-19 02:26:07 +08:00
parent fa54612642
commit faa613d671
11 changed files with 179 additions and 26 deletions

@ -4,9 +4,15 @@
#include <DPlatformWindowHandle> #include <DPlatformWindowHandle>
#include <DAboutDialog> #include <DAboutDialog>
#include <QStandardPaths>
#include <unistd.h>
Application::Application(int &argc, char **argv) Application::Application(int &argc, char **argv)
: DApplication(argc, argv) : DApplication(argc, argv)
{ {
saveLaunchParams(argc, argv);
loadTranslator(); loadTranslator();
setAttribute(Qt::AA_UseHighDpiPixmaps); setAttribute(Qt::AA_UseHighDpiPixmaps);
@ -35,6 +41,33 @@ void Application::handleAboutAction()
DApplication::handleAboutAction(); DApplication::handleAboutAction();
} }
QStringList Application::launchParams() const
{
return m_argv;
}
void Application::setMainWindow(MainWindow *window)
{
m_mainWindow = window;
}
MainWindow *Application::mainWindow()
{
return m_mainWindow;
}
void Application::saveLaunchParams(int &argc, char **argv)
{
m_argc = argc;
m_argv.clear();
for (int i = 0; i < m_argc; i++) {
m_argv.append(argv[i]);
}
qDebug() << Q_FUNC_INFO << m_argc << m_argv;
}
void Application::initAboutDialog() void Application::initAboutDialog()
{ {
// Customized DAboutDialog // Customized DAboutDialog

@ -1,6 +1,8 @@
#ifndef APPLICATION_H #ifndef APPLICATION_H
#define APPLICATION_H #define APPLICATION_H
#include "mainwindow.h"
#include <DApplication> #include <DApplication>
DWIDGET_USE_NAMESPACE DWIDGET_USE_NAMESPACE
@ -13,7 +15,13 @@ public:
Application(int &argc, char **argv); Application(int &argc, char **argv);
void handleAboutAction() override; void handleAboutAction() override;
QStringList launchParams() const;
void setMainWindow(MainWindow *window);
MainWindow *mainWindow();
private: private:
void saveLaunchParams(int &argc, char **argv);
void initAboutDialog(); void initAboutDialog();
signals: signals:
@ -21,6 +29,12 @@ signals:
public slots: public slots:
void slotMainWindowClose(); void slotMainWindowClose();
private:
MainWindow *m_mainWindow = nullptr;
int m_argc;
QStringList m_argv;
}; };
#endif // APPLICATION_H #endif // APPLICATION_H

@ -4,7 +4,7 @@
#include <QObject> #include <QObject>
#define DEFAULT_TITLE QObject::tr("SparkWebAppRuntime") #define DEFAULT_TITLE QObject::tr("SparkWebAppRuntime")
#define APPLICATION_NAME QString("SparkWebAppRuntime") #define APPLICATION_NAME QString("spark-webapp-runtime")
#define ORGANIZATION_NAME QString("spark-union") #define ORGANIZATION_NAME QString("spark-union")
#define DEFAULT_URL QString("qrc:/help/help.html") #define DEFAULT_URL QString("qrc:/help/help.html")
#define DEFAULT_WIDTH (1024) #define DEFAULT_WIDTH (1024)
@ -18,6 +18,6 @@
#define DEFAULT_PORT 0 #define DEFAULT_PORT 0
#define DEFAULT_GPU 1 #define DEFAULT_GPU 1
#define CURRENT_VER QString("1.6.6") #define CURRENT_VER QString("1.7.0")
#endif // GLOBALDEFINE_H #endif // GLOBALDEFINE_H

@ -44,8 +44,8 @@ int main(int argc, char *argv[])
int fakeArgc = argc + 2; int fakeArgc = argc + 2;
QVector<char *> fakeArgv(fakeArgc); QVector<char *> fakeArgv(fakeArgc);
fakeArgv[0] = argv[0]; fakeArgv[0] = argv[0];
fakeArgv[1] = QString("-platformtheme").toUtf8().data(); fakeArgv[1] = const_cast<char *>("-platformtheme");
fakeArgv[2] = QString("deepin").toUtf8().data(); fakeArgv[2] = const_cast<char *>("deepin");
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
fakeArgv[i + 2] = argv[i]; fakeArgv[i + 2] = argv[i];
} }
@ -347,6 +347,7 @@ int main(int argc, char *argv[])
#endif #endif
MainWindow w(szTitle, szUrl, width, height, tray, fullScreen, fixSize, hideButtons); MainWindow w(szTitle, szUrl, width, height, tray, fullScreen, fixSize, hideButtons);
a.setMainWindow(&w);
QObject::connect(&a, &Application::newInstanceStarted, &w, &MainWindow::slotNewInstanceStarted); QObject::connect(&a, &Application::newInstanceStarted, &w, &MainWindow::slotNewInstanceStarted);
QObject::connect(&w, &MainWindow::sigClose, &a, &Application::slotMainWindowClose); QObject::connect(&w, &MainWindow::sigClose, &a, &Application::slotMainWindowClose);

@ -3,6 +3,7 @@
#include "webengineview.h" #include "webengineview.h"
#include "webenginepage.h" #include "webenginepage.h"
#include <DLog>
#include <DWidgetUtil> #include <DWidgetUtil>
#include <DTitlebar> #include <DTitlebar>
#include <DMessageManager> #include <DMessageManager>
@ -15,6 +16,10 @@
#include <QDir> #include <QDir>
#include <QStandardPaths> #include <QStandardPaths>
#include <unistd.h>
DCORE_USE_NAMESPACE
MainWindow::MainWindow(QString szTitle, MainWindow::MainWindow(QString szTitle,
QString szUrl, QString szUrl,
int nWidth, int nWidth,
@ -56,6 +61,9 @@ MainWindow::MainWindow(QString szTitle,
, btnCancel(new DPushButton(QObject::tr("Cancel"), downloadProgressWidget)) , btnCancel(new DPushButton(QObject::tr("Cancel"), downloadProgressWidget))
, isCanceled(false) , isCanceled(false)
{ {
initTmpDir();
initLog();
initUI(); initUI();
initTrayIcon(); initTrayIcon();
initConnections(); initConnections();
@ -90,6 +98,18 @@ void MainWindow::setDescription(const QString &desc)
} }
} }
QString MainWindow::title() const
{
return m_title;
}
QString MainWindow::tmpDir() const
{
QString orgName = qobject_cast<DApplication *>(qApp)->organizationName();
QString appName = qobject_cast<DApplication *>(qApp)->applicationName();
return QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/" + orgName + "/" + appName + "/" + m_title + "/" + QString::number(getuid());
}
void MainWindow::keyPressEvent(QKeyEvent *event) void MainWindow::keyPressEvent(QKeyEvent *event)
{ {
if (!m_fixSize->isChecked()) // 固定窗口大小时禁止全屏 if (!m_fixSize->isChecked()) // 固定窗口大小时禁止全屏
@ -127,6 +147,29 @@ void MainWindow::closeEvent(QCloseEvent *event)
DMainWindow::closeEvent(event); DMainWindow::closeEvent(event);
} }
void MainWindow::initLog()
{
if (!QDir(tmpDir()).exists()) {
return;
}
DLogManager::setlogFilePath(tmpDir() + "/" + "log");
DLogManager::registerFileAppender();
DLogManager::registerConsoleAppender();
}
void MainWindow::initTmpDir()
{
QDir dir(tmpDir());
dir.removeRecursively();
dir.mkpath(dir.path());
if (!dir.exists()) {
qCritical() << Q_FUNC_INFO << dir.path() << "not exists";
return;
}
qDebug() << Q_FUNC_INFO << dir.path() << "created";
}
void MainWindow::initUI() void MainWindow::initUI()
{ {
// 初始化 MainWindow // 初始化 MainWindow

@ -36,12 +36,18 @@ public:
void setIcon(QString szIconPath); void setIcon(QString szIconPath);
void setDescription(const QString &desc); void setDescription(const QString &desc);
QString title() const;
QString tmpDir() const;
protected: protected:
void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent *event);
void resizeEvent(QResizeEvent *event); void resizeEvent(QResizeEvent *event);
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent *event);
private: private:
void initLog();
void initTmpDir();
void initUI(); void initUI();
void initTitleBar(); void initTitleBar();
void initDownloadProgressBar(); void initDownloadProgressBar();

@ -1,4 +1,4 @@
QT += core gui webenginewidgets svg concurrent QT += core gui webenginewidgets svg concurrent dbus
greaterThan(QT_MAJOR_VERSION, 5): QT += widgets greaterThan(QT_MAJOR_VERSION, 5): QT += widgets

@ -4,12 +4,12 @@
<context> <context>
<name>DAboutDialog</name> <name>DAboutDialog</name>
<message> <message>
<location filename="../application.cpp" line="49"/> <location filename="../application.cpp" line="82"/>
<source>Version: %1</source> <source>Version: %1</source>
<translation>%1</translation> <translation>%1</translation>
</message> </message>
<message> <message>
<location filename="../application.cpp" line="65"/> <location filename="../application.cpp" line="98"/>
<source>%1 is released under %2</source> <source>%1 is released under %2</source>
<translation>%1%2</translation> <translation>%1%2</translation>
</message> </message>
@ -17,7 +17,7 @@
<context> <context>
<name>QObject</name> <name>QObject</name>
<message> <message>
<location filename="../application.cpp" line="57"/> <location filename="../application.cpp" line="90"/>
<location filename="../main.cpp" line="186"/> <location filename="../main.cpp" line="186"/>
<source>Presented By Spark developers # HadesStudio</source> <source>Presented By Spark developers # HadesStudio</source>
<translation> @ </translation> <translation> @ </translation>
@ -113,95 +113,100 @@
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="42"/> <location filename="../mainwindow.cpp" line="47"/>
<source>Full Screen</source> <source>Full Screen</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="43"/> <location filename="../mainwindow.cpp" line="48"/>
<source>Fix Size</source> <source>Fix Size</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="44"/> <location filename="../mainwindow.cpp" line="49"/>
<source>Hide Buttons</source> <source>Hide Buttons</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="45"/> <location filename="../mainwindow.cpp" line="50"/>
<source>Clear Cache</source> <source>Clear Cache</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="47"/> <location filename="../mainwindow.cpp" line="52"/>
<source>Show MainWindow</source> <source>Show MainWindow</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="54"/> <location filename="../mainwindow.cpp" line="59"/>
<source>Pause</source> <source>Pause</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="55"/> <location filename="../mainwindow.cpp" line="60"/>
<source>Resume</source> <source>Resume</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="56"/> <location filename="../mainwindow.cpp" line="61"/>
<source>Cancel</source> <source>Cancel</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="338"/> <location filename="../mainwindow.cpp" line="381"/>
<source>Save As</source> <source>Save As</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="402"/> <location filename="../mainwindow.cpp" line="445"/>
<source>%1Start downloading %2</source> <source>%1Start downloading %2</source>
<translation>%1 %2</translation> <translation>%1 %2</translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="413"/> <location filename="../mainwindow.cpp" line="456"/>
<source>%1Wait for previous download to complete!</source> <source>%1Wait for previous download to complete!</source>
<translation>%1</translation> <translation>%1</translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="435"/> <location filename="../mainwindow.cpp" line="478"/>
<source>Open</source> <source>Open</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="439"/> <location filename="../mainwindow.cpp" line="482"/>
<source>download finished.</source> <source>download finished.</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="439"/> <location filename="../mainwindow.cpp" line="482"/>
<source>Show in file manager?</source> <source>Show in file manager?</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="477"/> <location filename="../mainwindow.cpp" line="520"/>
<source>%1Download canceled!</source> <source>%1Download canceled!</source>
<translation>%1</translation> <translation>%1</translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="482"/> <location filename="../mainwindow.cpp" line="525"/>
<source>%1Load error occurred!</source> <source>%1Load error occurred!</source>
<translation>%1</translation> <translation>%1</translation>
</message> </message>
<message>
<location filename="../webengineview.cpp" line="79"/>
<source>View</source>
<translation></translation>
</message>
</context> </context>
<context> <context>
<name>TitleBarMenu</name> <name>TitleBarMenu</name>
<message> <message>
<location filename="../mainwindow.cpp" line="48"/> <location filename="../mainwindow.cpp" line="53"/>
<source>About</source> <source>About</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="49"/> <location filename="../mainwindow.cpp" line="54"/>
<source>Exit</source> <source>Exit</source>
<translation>退</translation> <translation>退</translation>
</message> </message>

@ -5,6 +5,13 @@
WebEnginePage::WebEnginePage(QObject *parent) WebEnginePage::WebEnginePage(QObject *parent)
: QWebEnginePage(parent) : QWebEnginePage(parent)
{ {
connect(this, &QWebEnginePage::featurePermissionRequested, [&](const QUrl &origin, QWebEnginePage::Feature feature) {
if (feature != QWebEnginePage::Notifications) {
return;
}
setFeaturePermission(origin, feature, QWebEnginePage::PermissionGrantedByUser);
});
} }
WebEnginePage::~WebEnginePage() WebEnginePage::~WebEnginePage()

@ -1,13 +1,17 @@
#include "webengineview.h" #include "webengineview.h"
//#include "webengineurlrequestinterceptor.h" //#include "webengineurlrequestinterceptor.h"
#include "application.h"
#include <DGuiApplicationHelper> #include <DGuiApplicationHelper>
#include <DNotifySender>
#include <QWebEngineSettings> #include <QWebEngineSettings>
#include <QWebEngineProfile> #include <QWebEngineProfile>
#include <QLocale> #include <QLocale>
#include <QFileInfo>
DGUI_USE_NAMESPACE DGUI_USE_NAMESPACE
DCORE_USE_NAMESPACE
WebEngineView::WebEngineView(QWidget *parent) WebEngineView::WebEngineView(QWidget *parent)
: QWebEngineView(parent) : QWebEngineView(parent)
@ -17,6 +21,9 @@ WebEngineView::WebEngineView(QWidget *parent)
// page()->setUrlRequestInterceptor(interceptor); // page()->setUrlRequestInterceptor(interceptor);
// page()->settings()->setAttribute(QWebEngineSettings::WebAttribute::LocalContentCanAccessRemoteUrls, true); // page()->settings()->setAttribute(QWebEngineSettings::WebAttribute::LocalContentCanAccessRemoteUrls, true);
page()->profile()->setHttpAcceptLanguage(QLocale::system().name()); page()->profile()->setHttpAcceptLanguage(QLocale::system().name());
page()->profile()->setNotificationPresenter([&](std::unique_ptr<QWebEngineNotification> notification) {
WebEngineView::present(notification);
});
}); });
} }
@ -51,3 +58,38 @@ void WebEngineView::handleChromiumFlags()
qDebug() << Q_FUNC_INFO << "QTWEBENGINE_CHROMIUM_FLAGS=" + qgetenv("QTWEBENGINE_CHROMIUM_FLAGS"); qDebug() << Q_FUNC_INFO << "QTWEBENGINE_CHROMIUM_FLAGS=" + qgetenv("QTWEBENGINE_CHROMIUM_FLAGS");
} }
void WebEngineView::present(std::unique_ptr<QWebEngineNotification> &newNotification)
{
qDebug() << Q_FUNC_INFO << "New notification received:" << newNotification->title() << newNotification->message();
QImage image = newNotification->icon();
QString tmpDir = qobject_cast<Application *>(qApp)->mainWindow()->tmpDir();
QString appIcon = tmpDir + "/" + "icon.png";
if (QFileInfo::exists(appIcon)) {
QFile::remove(appIcon);
}
image.save(appIcon, "PNG");
QString summary = newNotification->title();
QString appName = qobject_cast<Application *>(qApp)->mainWindow()->title();
QString appBody = newNotification->message();
quint32 replaceId = 0;
int timeOut = 3000;
QStringList actions = QStringList() << "view" << QObject::tr("View");
QString launchCmd = qobject_cast<Application *>(qApp)->launchParams().join(",");
qDebug() << launchCmd;
QVariantMap hints;
hints.insert("x-deepin-action-view", launchCmd);
DUtil::DNotifySender(summary)
.appName(appName)
.appIcon(appIcon)
.appBody(appBody)
.replaceId(replaceId)
.timeOut(timeOut)
.actions(actions)
.hints(hints)
.call();
}

@ -2,6 +2,7 @@
#define WEBENGINEVIEW_H #define WEBENGINEVIEW_H
#include <QWebEngineView> #include <QWebEngineView>
#include <QWebEngineNotification>
// class WebEngineUrlRequestInterceptor; // class WebEngineUrlRequestInterceptor;
class WebEngineView : public QWebEngineView class WebEngineView : public QWebEngineView
@ -12,6 +13,7 @@ public:
explicit WebEngineView(QWidget *parent = nullptr); explicit WebEngineView(QWidget *parent = nullptr);
static void handleChromiumFlags(); static void handleChromiumFlags();
static void present(std::unique_ptr<QWebEngineNotification> &newNotification);
private: private:
// WebEngineUrlRequestInterceptor *interceptor = nullptr; // WebEngineUrlRequestInterceptor *interceptor = nullptr;