feat: 限制同标题进程单例运行;网页链接调用浏览器打开

使用 DApplication::setSingleInstance,使用 标题_uid 创建进程锁,单例运行时新进程自动退出,并拉起原有进程主窗口显示;重写 QWebEnginePage,createWindow 时若链接与原来不同,则调用浏览器打开

Log: 支持单例运行;支持浏览器打开外部链接;修复访问深度论坛默认语言错误问题
This commit is contained in:
zty199 2022-11-20 15:57:54 +08:00
parent d6b5895812
commit 1aed5532a3
18 changed files with 494 additions and 285 deletions

@ -1,6 +1,6 @@
TEMPLATE = subdirs TEMPLATE = subdirs
SUBDIRS += \ SUBDIRS += \
spark-webapp-runtime spark-webapp-runtime
CONFIG += ordered CONFIG += ordered

@ -0,0 +1,81 @@
#include "application.h"
#include "globaldefine.h"
#include <DPlatformWindowHandle>
#include <DAboutDialog>
Application::Application(int &argc, char **argv)
: DApplication(argc, argv)
{
loadTranslator();
setAttribute(Qt::AA_UseHighDpiPixmaps);
if (!DPlatformWindowHandle::pluginVersion().isEmpty()) {
setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true);
}
setApplicationVersion(QString(CURRENT_VER));
setOrganizationName(ORGANIZATION_NAME); // 添加组织名称,和商店主体的文件夹同在 ~/.local/share/spark-union 文件夹下
setApplicationName(APPLICATION_NAME); // 这里不要翻译,否则 ~/.local/share 中文件夹名也会被翻译
setProductName(DEFAULT_TITLE);
setApplicationDisplayName(DEFAULT_TITLE);
setApplicationLicense(" <a href='https://www.gnu.org/licenses/gpl-3.0.html'>GPLv3</a> ");
initAboutDialog();
}
void Application::handleAboutAction()
{
if (aboutDialog()) {
DApplication::handleAboutAction();
return;
}
initAboutDialog();
DApplication::handleAboutAction();
}
void Application::initAboutDialog()
{
// Customized DAboutDialog
DAboutDialog *dialog = new DAboutDialog(activeWindow());
// WindowIcon
dialog->setWindowIcon(QIcon(":/images/spark-webapp-runtime.svg"));
// ProductIcon
dialog->setProductIcon(QIcon(":/images/spark-webapp-runtime.svg"));
// ProductName
dialog->setProductName(productName());
// Version
dialog->setVersion(translate("DAboutDialog", "Version: %1").arg(applicationVersion()));
// CompanyLogo
dialog->setCompanyLogo(QPixmap(":/images/Logo-Spark.png"));
// Description
QString szDefaultDesc = QString("<a href='https://gitee.com/deepin-community-store/spark-web-app-runtime'><span style='font-size:12pt;font-weight:500;'>%1</span></a><br/>"
"<span style='font-size:12pt;'>%2</span>")
.arg(DEFAULT_TITLE)
.arg(QObject::tr("Presented By Spark developers # HadesStudio"));
dialog->setDescription(szDefaultDesc);
// WebsiteName
dialog->setWebsiteName("Spark Project");
// WebsiteLink
dialog->setWebsiteLink("https://gitee.com/deepin-community-store/");
// License
dialog->setLicense(translate("DAboutDialog", "%1 is released under %2").arg(productName()).arg(applicationLicense()));
setAboutDialog(dialog);
connect(aboutDialog(), &DAboutDialog::destroyed, this, [=] {
setAboutDialog(nullptr);
});
dialog->hide();
}
void Application::slotMainWindowClose()
{
if (aboutDialog()) {
aboutDialog()->close();
aboutDialog()->deleteLater();
}
}

@ -0,0 +1,26 @@
#ifndef APPLICATION_H
#define APPLICATION_H
#include <DApplication>
DWIDGET_USE_NAMESPACE
class Application : public DApplication
{
Q_OBJECT
public:
Application(int &argc, char **argv);
void handleAboutAction() override;
private:
void initAboutDialog();
signals:
void sigQuit();
public slots:
void slotMainWindowClose();
};
#endif // APPLICATION_H

@ -10,8 +10,8 @@
#define DEFAULT_WIDTH (1024) #define DEFAULT_WIDTH (1024)
#define DEFAULT_HEIGHT (768) #define DEFAULT_HEIGHT (768)
#define DEFAULT_DESC QString()
#define DEFAULT_ICON QString() #define DEFAULT_ICON QString()
#define DEFAULT_DESC QString()
#define DEFAULT_CFG QString() #define DEFAULT_CFG QString()
#define DEFAULT_ROOT QString() #define DEFAULT_ROOT QString()

@ -1,30 +1,28 @@
/* /**
* * Spark WebApp Runtime
* *
*/ */
#include "application.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "globaldefine.h"
#include "httpd.h"
#include <DApplication> #include <DSysInfo>
#include <DPlatformWindowHandle>
#include <QCommandLineParser> #include <QCommandLineParser>
#include <QCommandLineOption> #include <QCommandLineOption>
#include <QFileInfo> #include <QFileInfo>
#include <QSettings> #include <QSettings>
#include <QVector>
#include "globaldefine.h" #include <unistd.h>
#include "httpd.h"
DWIDGET_USE_NAMESPACE
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
if (!QString(qgetenv("XDG_CURRENT_DESKTOP")).toLower().startsWith("deepin")) { if (!QString(qgetenv("XDG_CURRENT_DESKTOP")).toLower().startsWith("deepin")) {
setenv("XDG_CURRENT_DESKTOP", "Deepin", 1); qputenv("XDG_CURRENT_DESKTOP", "Deepin");
} }
// 龙芯机器配置,使得DApplication能正确加载QTWEBENGINE // 龙芯机器配置,使得 DApplication 能正确加载 QTWEBENGINE
qputenv("DTK_FORCE_RASTER_WIDGETS", "FALSE"); qputenv("DTK_FORCE_RASTER_WIDGETS", "FALSE");
// qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--disable-features=UseModernMediaControls"); // qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--disable-features=UseModernMediaControls");
// qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--disable-web-security"); // qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--disable-web-security");
@ -32,60 +30,27 @@ int main(int argc, char *argv[])
qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--no-sandbox"); qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--no-sandbox");
#endif #endif
if (!Dtk::Core::DSysInfo::isDDE()) {
#ifndef DSTORE_NO_DXCBs #ifndef DSTORE_NO_DXCBs
Dtk::Widget::DApplication::loadDXcbPlugin(); DApplication::loadDXcbPlugin();
#endif #endif
// 强制使用DTK平台插件
QVector<char *> fakeArgv(argc + 2);
fakeArgv[0] = argv[0];
fakeArgv[1] = "-platformtheme";
fakeArgv[2] = "deepin";
for(int i = 1; i < argc; i++) fakeArgv[i + 2] = argv[i];
int fakeArgc = argc + 2;
DApplication a(fakeArgc, fakeArgv.data());
a.loadTranslator();
a.setAttribute(Qt::AA_UseHighDpiPixmaps);
if (!Dtk::Widget::DPlatformWindowHandle::pluginVersion().isEmpty()) {
a.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true);
} }
a.setApplicationVersion(QString(CURRENT_VER)); // 开启 HiDPI 缩放支持
a.setOrganizationName(ORGANIZATION_NAME); // 添加组织名称,和商店主体的文件夹同在 ~/.local/share/spark-union 文件夹下 DApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
a.setApplicationName(APPLICATION_NAME); // 这里不要翻译,否则 ~/.local/share 中文件夹名也会被翻译
a.setProductName(DEFAULT_TITLE);
a.setApplicationDisplayName(DEFAULT_TITLE);
// Customized DAboutDialog (Can't work on other distro like Ubuntu...) // 强制使用 DTK 平台插件
DAboutDialog *dialog = new DAboutDialog; int fakeArgc = argc + 2;
a.setAboutDialog(dialog); QVector<char *> fakeArgv(fakeArgc);
fakeArgv[0] = argv[0];
// WindowIcon fakeArgv[1] = QString("-platformtheme").toUtf8().data();
dialog->setWindowIcon(QIcon(":/images/spark-webapp-runtime.svg")); fakeArgv[2] = QString("deepin").toUtf8().data();
// ProductIcon for (int i = 1; i < argc; i++) {
dialog->setProductIcon(QIcon(":/images/spark-webapp-runtime.svg")); fakeArgv[i + 2] = argv[i];
// ProductName }
dialog->setProductName(QString("<span>%1</span>").arg(DEFAULT_TITLE)); Application a(fakeArgc, fakeArgv.data());
// Version
dialog->setVersion(QString("%1 %2").arg(QObject::tr("Version:")).arg(CURRENT_VER));
// CompanyLogo
dialog->setCompanyLogo(QPixmap(":/images/Logo-Spark.png"));
// Description
QString szDefaultDesc = QString("<a href='https://gitee.com/deepin-community-store/spark-web-app-runtime'><span style='font-size:12pt;font-weight:500;'>%1</span></a><br/>"
"<span style='font-size:12pt;'>%2</span>")
.arg(DEFAULT_TITLE)
.arg(QObject::tr("Presented By Spark developers # HadesStudio"));
dialog->setDescription(szDefaultDesc);
// WebsiteName
dialog->setWebsiteName("Spark Project");
// WebsiteLink
dialog->setWebsiteLink("https://gitee.com/deepin-community-store/");
// License
dialog->setLicense(QObject::tr("Published under GPLv3"));
// 解析命令行启动参数
QCommandLineParser parser; QCommandLineParser parser;
parser.setApplicationDescription(QObject::tr("Description: %1").arg(DEFAULT_TITLE)); parser.setApplicationDescription(QObject::tr("Description: %1").arg(DEFAULT_TITLE));
@ -174,15 +139,14 @@ int main(int argc, char *argv[])
<< "port", << "port",
QObject::tr("The port number of the program web service."), QObject::tr("The port number of the program web service."),
"port", "port",
DEFAULT_PORT); QString::number(DEFAULT_PORT));
parser.addOption(optPort); parser.addOption(optPort);
QCommandLineOption useGPU(QStringList() << "G" QCommandLineOption useGPU(QStringList() << "G"
<< "GPU", << "GPU",
QObject::tr("To use GPU instead of CPU to decoding. Default True."), QObject::tr("To use GPU instead of CPU to decoding. Default True."),
"GPU", "GPU",
QString::number(DEFAULT_GPU)); QString::number(DEFAULT_GPU));
parser.addOption(useGPU); parser.addOption(useGPU);
#if SSL_SERVER #if SSL_SERVER
@ -212,7 +176,12 @@ int main(int argc, char *argv[])
#if SSL_SERVER #if SSL_SERVER
quint16 u16sslPort = 0; quint16 u16sslPort = 0;
#endif #endif
QString szDefaultDesc = QString("<a href='https://gitee.com/deepin-community-store/spark-web-app-runtime'><span style='font-size:12pt;font-weight:500;'>%1</span></a><br/>"
"<span style='font-size:12pt;'>%2</span>")
.arg(DEFAULT_TITLE)
.arg(QObject::tr("Presented By Spark developers # HadesStudio"));
// 解析可能存在的配置文件
QString szCfgFile = DEFAULT_CFG; QString szCfgFile = DEFAULT_CFG;
if (parser.isSet(optCfgFile)) { if (parser.isSet(optCfgFile)) {
szCfgFile = parser.value(optCfgFile); szCfgFile = parser.value(optCfgFile);
@ -232,7 +201,7 @@ int main(int argc, char *argv[])
.arg(settings.value("SparkWebAppRuntime/Desc", QString()).toString()) .arg(settings.value("SparkWebAppRuntime/Desc", QString()).toString())
.arg(szDefaultDesc); .arg(szDefaultDesc);
szRootPath = settings.value("SparkWebAppRuntime/RootPath", QString()).toString(); szRootPath = settings.value("SparkWebAppRuntime/RootPath", QString()).toString();
u16Port = settings.value("SparkWebAppRuntime/Port", 0).toUInt(); u16Port = static_cast<quint16>(settings.value("SparkWebAppRuntime/Port", 0).toUInt());
#if SSL_SERVER #if SSL_SERVER
u16sslPort = settings.value("SparkWebAppRuntime/SSLPort", 0).toUInt(); u16sslPort = settings.value("SparkWebAppRuntime/SSLPort", 0).toUInt();
#endif #endif
@ -267,6 +236,9 @@ int main(int argc, char *argv[])
hideButtons = true; hideButtons = true;
} }
if (parser.isSet(optIcon)) {
szIcon = parser.value(optIcon);
}
if (parser.isSet(optDesc)) { if (parser.isSet(optDesc)) {
szDesc = QString("%1<br/><br/>%2").arg(parser.value(optDesc)).arg(szDefaultDesc); szDesc = QString("%1<br/><br/>%2").arg(parser.value(optDesc)).arg(szDefaultDesc);
} }
@ -276,17 +248,17 @@ int main(int argc, char *argv[])
} }
if (parser.isSet(optPort)) { if (parser.isSet(optPort)) {
u16Port = parser.value(optPort).toUInt(); u16Port = static_cast<quint16>(parser.value(optPort).toUInt());
} }
if (parser.isSet(useGPU)) { if (parser.isSet(useGPU)) {
toUseGPU = parser.value(useGPU).toUInt(); toUseGPU = parser.value(useGPU).toUInt();
} }
if (toUseGPU == true){ if (toUseGPU == true) {
qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--ignore-gpu-blocklist --enable-gpu-rasterization --enable-native-gpu-memory-buffers --enable-accelerated-video-decode"); qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--ignore-gpu-blocklist --enable-gpu-rasterization --enable-native-gpu-memory-buffers --enable-accelerated-video-decode --blink-settings=darkMode=4,darkModeImagePolicy=2");
#ifdef __sw_64__ #ifdef __sw_64__
qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--ignore-gpu-blocklist --enable-gpu-rasterization --enable-native-gpu-memory-buffers --enable-accelerated-video-decode --no-sandbox"); qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--ignore-gpu-blocklist --enable-gpu-rasterization --enable-native-gpu-memory-buffers --enable-accelerated-video-decode --blink-settings=darkMode=4,darkModeImagePolicy=2 --no-sandbox");
#endif #endif
qDebug() << "Setting GPU to True."; qDebug() << "Setting GPU to True.";
} }
@ -335,7 +307,7 @@ int main(int argc, char *argv[])
szRootPath = QString(argv[11]); szRootPath = QString(argv[11]);
} }
if (argc > 12) { if (argc > 12) {
u16Port = QString(argv[12]).toUInt(); u16Port = static_cast<quint16>(QString(argv[12]).toUInt());
} }
#if SSL_SERVER #if SSL_SERVER
if (argc > 13) { if (argc > 13) {
@ -348,10 +320,13 @@ int main(int argc, char *argv[])
fullScreen = false; // 固定窗口大小时禁用全屏模式,避免标题栏按钮 BUG fullScreen = false; // 固定窗口大小时禁用全屏模式,避免标题栏按钮 BUG
} }
// DApplication 单例运行标题名称_当前登录用户 id
if (!a.setSingleInstance(szTitle + "_" + QString::number(getuid()))) {
qInfo() << "Another instance has already started, now exit...";
exit(0);
}
a.setQuitOnLastWindowClosed(!tray); // 启用托盘时,退出程序后服务不终止 a.setQuitOnLastWindowClosed(!tray); // 启用托盘时,退出程序后服务不终止
MainWindow w(szTitle, szUrl, width, height, tray, fullScreen, fixSize, hideButtons, dialog);
#if SSL_SERVER #if SSL_SERVER
if (!szRootPath.isEmpty() && u16Port > 0 && u16sslPort > 0) { if (!szRootPath.isEmpty() && u16Port > 0 && u16sslPort > 0) {
HttpD httpd(szRootPath, u16Port, u16sslPort); HttpD httpd(szRootPath, u16Port, u16sslPort);
@ -360,24 +335,23 @@ int main(int argc, char *argv[])
#else #else
if (!szRootPath.isEmpty() && u16Port > 0) { if (!szRootPath.isEmpty() && u16Port > 0) {
static HttpD httpd(szRootPath, u16Port); static HttpD httpd(szRootPath, u16Port);
QObject::connect(&w, &MainWindow::sigQuit, &httpd, &HttpD::stop); QObject::connect(&a, &Application::sigQuit, &httpd, &HttpD::stop);
httpd.start(); httpd.start();
} }
#endif #endif
if (parser.isSet(optIcon)) { MainWindow w(szTitle, szUrl, width, height, tray, fullScreen, fixSize, hideButtons);
szIcon = parser.value(optIcon); QObject::connect(&a, &Application::newInstanceStarted, &w, &MainWindow::slotNewInstanceStarted);
} QObject::connect(&w, &MainWindow::sigClose, &a, &Application::slotMainWindowClose);
if (!szIcon.isEmpty()) { if (!szIcon.isEmpty()) {
dialog->setWindowIcon(QIcon(szIcon));
dialog->setProductIcon(QIcon(szIcon));
w.setIcon(szIcon); w.setIcon(szIcon);
} }
if (!szDesc.isEmpty()) { if (!szDesc.isEmpty()) {
dialog->setDescription(szDesc); w.setDescription(szDesc);
} }
w.show(); w.show();
return a.exec(); return a.exec();
} }

@ -1,16 +1,19 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "application.h"
#include "webengineview.h"
#include "webenginepage.h"
#include <DWidgetUtil> #include <DWidgetUtil>
#include <DTitlebar> #include <DTitlebar>
#include <DMessageManager> #include <DMessageManager>
#include <DDesktopServices> #include <DDesktopServices>
#include <QKeyEvent>
#include <QWebEngineProfile>
#include <QFileInfo> #include <QFileInfo>
#include <QFileDialog> #include <QFileDialog>
#include <QDir> #include <QDir>
#include <QCloseEvent> #include <QStandardPaths>
#include "webengineview.h"
MainWindow::MainWindow(QString szTitle, MainWindow::MainWindow(QString szTitle,
QString szUrl, QString szUrl,
@ -20,7 +23,6 @@ MainWindow::MainWindow(QString szTitle,
bool nFullScreen, bool nFullScreen,
bool nFixSize, bool nFixSize,
bool nHideButtons, bool nHideButtons,
QDialog *dialog,
QWidget *parent) QWidget *parent)
: DMainWindow(parent) : DMainWindow(parent)
, m_title(szTitle) , m_title(szTitle)
@ -32,27 +34,26 @@ MainWindow::MainWindow(QString szTitle,
, m_isFixedSize(nFixSize) , m_isFixedSize(nFixSize)
, m_isHideButton(nHideButtons) , m_isHideButton(nHideButtons)
, m_widget(new Widget(m_url, this)) , m_widget(new Widget(m_url, this))
, m_dialog(dynamic_cast<DAboutDialog *>(dialog))
, m_tray(new QSystemTrayIcon(this)) , m_tray(new QSystemTrayIcon(this))
, btnBack(new DToolButton(titlebar())) , btnBack(new DToolButton(titlebar()))
, btnForward(new DToolButton(titlebar())) , btnForward(new DToolButton(titlebar()))
, btnRefresh(new DToolButton(titlebar())) , btnRefresh(new DToolButton(titlebar()))
, m_menu(new QMenu(titlebar())) , m_menu(new QMenu(titlebar()))
, m_fullScreen(new QAction(tr("Full Screen"), this)) , m_fullScreen(new QAction(QObject::tr("Full Screen"), this))
, m_fixSize(new QAction(tr("Fix Size"), this)) , m_fixSize(new QAction(QObject::tr("Fix Size"), this))
, m_hideButtons(new QAction(tr("Hide Buttons"), this)) , m_hideButtons(new QAction(QObject::tr("Hide Buttons"), this))
, m_clearCache(new QAction(tr("Clear Cache"), this)) , m_clearCache(new QAction(QObject::tr("Clear Cache"), this))
, t_menu(new QMenu(this)) , t_menu(new QMenu(this))
, t_show(new QAction(tr("Show MainWindow"), this)) , t_show(new QAction(QObject::tr("Show MainWindow"), this))
, t_about(new QAction(tr("About"), this)) , t_about(new QAction(qApp->translate("TitleBarMenu", "About"), this))
, t_exit(new QAction(tr("Exit"), this)) , t_exit(new QAction(qApp->translate("TitleBarMenu", "Exit"), this))
, downloadMessage(new DFloatingMessage(DFloatingMessage::ResidentType, this)) , downloadMessage(new DFloatingMessage(DFloatingMessage::ResidentType, this))
, downloadProgressWidget(new QWidget(downloadMessage)) , downloadProgressWidget(new QWidget(downloadMessage))
, progressBarLayout(new QHBoxLayout(downloadProgressWidget)) , progressBarLayout(new QHBoxLayout(downloadProgressWidget))
, downloadProgressBar(new DProgressBar(downloadProgressWidget)) , downloadProgressBar(new DProgressBar(downloadProgressWidget))
, btnPause(new DPushButton(tr("Pause"), downloadProgressWidget)) , btnPause(new DPushButton(QObject::tr("Pause"), downloadProgressWidget))
, btnResume(new DPushButton(tr("Resume"), downloadProgressWidget)) , btnResume(new DPushButton(QObject::tr("Resume"), downloadProgressWidget))
, btnCancel(new DPushButton(tr("Cancel"), downloadProgressWidget)) , btnCancel(new DPushButton(QObject::tr("Cancel"), downloadProgressWidget))
, isCanceled(false) , isCanceled(false)
{ {
initUI(); initUI();
@ -62,16 +63,30 @@ MainWindow::MainWindow(QString szTitle,
MainWindow::~MainWindow() MainWindow::~MainWindow()
{ {
emit sigQuit();
delete m_dialog;
} }
void MainWindow::setIcon(QString szIconPath) void MainWindow::setIcon(QString szIconPath)
{ {
if (QFileInfo(szIconPath).exists()) { if (!QFileInfo(szIconPath).exists()) {
titlebar()->setIcon(QIcon(szIconPath)); return;
setWindowIcon(QIcon(szIconPath)); }
m_tray->setIcon(QIcon(szIconPath));
titlebar()->setIcon(QIcon(szIconPath));
setWindowIcon(QIcon(szIconPath));
m_tray->setIcon(QIcon(szIconPath));
DAboutDialog *aboutDialog = qobject_cast<Application *>(qApp)->aboutDialog();
if (aboutDialog) {
aboutDialog->setWindowIcon(QIcon::fromTheme(szIconPath));
aboutDialog->setProductIcon(QIcon::fromTheme(szIconPath));
}
}
void MainWindow::setDescription(const QString &desc)
{
DAboutDialog *aboutDialog = qobject_cast<Application *>(qApp)->aboutDialog();
if (aboutDialog) {
aboutDialog->setDescription(desc);
} }
} }
@ -85,7 +100,8 @@ void MainWindow::keyPressEvent(QKeyEvent *event)
m_menu->update(); m_menu->update();
} }
} }
event->accept();
DMainWindow::keyPressEvent(event);
} }
void MainWindow::resizeEvent(QResizeEvent *event) void MainWindow::resizeEvent(QResizeEvent *event)
@ -98,15 +114,17 @@ void MainWindow::resizeEvent(QResizeEvent *event)
m_fixSize->setEnabled(true); // 命令行参数没有固定窗口大小时,窗口模式下允许手动选择固定窗口大小 m_fixSize->setEnabled(true); // 命令行参数没有固定窗口大小时,窗口模式下允许手动选择固定窗口大小
} }
} }
DMainWindow::resizeEvent(event); DMainWindow::resizeEvent(event);
} }
void MainWindow::closeEvent(QCloseEvent *event) void MainWindow::closeEvent(QCloseEvent *event)
{ {
if (!m_isTrayEnabled) { if (!m_isTrayEnabled) {
m_dialog->close(); // 不启用托盘时,关闭主窗口则关闭关于窗口 emit sigClose(); // 不启用托盘时,关闭主窗口则关闭关于窗口
} }
event->accept();
DMainWindow::closeEvent(event);
} }
void MainWindow::initUI() void MainWindow::initUI()
@ -240,8 +258,7 @@ void MainWindow::initConnections()
fixSize(); fixSize();
}); });
connect(t_about, &QAction::triggered, this, [=]() { connect(t_about, &QAction::triggered, this, [=]() {
m_dialog->activateWindow(); qobject_cast<Application *>(qApp)->handleAboutAction();
m_dialog->show();
}); });
connect(t_exit, &QAction::triggered, this, [=]() { connect(t_exit, &QAction::triggered, this, [=]() {
exit(0); exit(0);
@ -262,14 +279,14 @@ void MainWindow::fullScreen()
m_fixSize->setDisabled(true); m_fixSize->setDisabled(true);
m_menu->update(); m_menu->update();
showFullScreen(); showFullScreen();
// DMessageManager::instance()->sendMessage(this, QIcon::fromTheme("dialog-information").pixmap(64, 64), QString(tr("%1Fullscreen Mode")).arg(" ")); // DMessageManager::instance()->sendMessage(this, QIcon::fromTheme("dialog-information").pixmap(64, 64), QString(QObject::tr("%1Fullscreen Mode")).arg(" "));
} else { } else {
if (!m_isFixedSize) { if (!m_isFixedSize) {
m_fixSize->setDisabled(false); // 命令行参数没有固定窗口大小时,窗口模式下允许手动选择固定窗口大小 m_fixSize->setDisabled(false); // 命令行参数没有固定窗口大小时,窗口模式下允许手动选择固定窗口大小
} }
m_menu->update(); m_menu->update();
showNormal(); showNormal();
// DMessageManager::instance()->sendMessage(this, QIcon::fromTheme("dialog-information").pixmap(64, 64), QString(tr("%1Windowed Mode")).arg(" ")); // DMessageManager::instance()->sendMessage(this, QIcon::fromTheme("dialog-information").pixmap(64, 64), QString(QObject::tr("%1Windowed Mode")).arg(" "));
} }
} }
@ -307,7 +324,7 @@ void MainWindow::hideButtons()
void MainWindow::clearCache() void MainWindow::clearCache()
{ {
// 清除缓存文件夹并刷新页面 // 清除缓存文件夹并刷新页面
QDir dir(QDir::homePath() + "/.local/share/" + ORGANIZATION_NAME + "/" + APPLICATION_NAME); QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation));
if (dir.exists()) { if (dir.exists()) {
dir.removeRecursively(); dir.removeRecursively();
} }
@ -317,7 +334,9 @@ void MainWindow::clearCache()
QString MainWindow::saveAs(QString fileName) QString MainWindow::saveAs(QString fileName)
{ {
QString saveFile = QFileDialog::getSaveFileName(this, tr("Save As"), QDir::homePath() + "/Downloads/" + fileName); QString saveFile = QFileDialog::getSaveFileName(this,
QObject::tr("Save As"),
QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) + "/" + fileName);
if (!saveFile.isEmpty()) { if (!saveFile.isEmpty()) {
// 判断上层目录是否可写入 // 判断上层目录是否可写入
if (QFileInfo(QFileInfo(saveFile).absolutePath()).isWritable()) { if (QFileInfo(QFileInfo(saveFile).absolutePath()).isWritable()) {
@ -329,11 +348,19 @@ QString MainWindow::saveAs(QString fileName)
return nullptr; return nullptr;
} }
void MainWindow::slotNewInstanceStarted()
{
this->setWindowState(Qt::WindowActive);
this->activateWindow();
this->show();
}
void MainWindow::on_trayIconActivated(QSystemTrayIcon::ActivationReason reason) void MainWindow::on_trayIconActivated(QSystemTrayIcon::ActivationReason reason)
{ {
switch (reason) { switch (reason) {
/* 响应托盘点击事件 */ /* 响应托盘点击事件 */
case QSystemTrayIcon::Trigger: case QSystemTrayIcon::Trigger:
this->setWindowState(Qt::WindowActive);
this->activateWindow(); this->activateWindow();
fixSize(); fixSize();
break; break;
@ -372,7 +399,7 @@ void MainWindow::on_downloadStart(QWebEngineDownloadItem *item)
DFloatingMessage *message = new DFloatingMessage(DFloatingMessage::TransientType); DFloatingMessage *message = new DFloatingMessage(DFloatingMessage::TransientType);
message->setIcon(QIcon::fromTheme("dialog-information").pixmap(64, 64)); message->setIcon(QIcon::fromTheme("dialog-information").pixmap(64, 64));
message->setMessage(QString(tr("%1Start downloading %2")).arg(" ").arg(fileName)); message->setMessage(QString(QObject::tr("%1Start downloading %2")).arg(" ").arg(fileName));
DMessageManager::instance()->sendMessage(this, message); DMessageManager::instance()->sendMessage(this, message);
item->accept(); item->accept();
@ -383,7 +410,7 @@ void MainWindow::on_downloadStart(QWebEngineDownloadItem *item)
btnPause->show(); btnPause->show();
this->downloadMessage->show(); // 上一次下载完成后隐藏了进度条,这里要重新显示 this->downloadMessage->show(); // 上一次下载完成后隐藏了进度条,这里要重新显示
} else { } else {
DMessageManager::instance()->sendMessage(this, QIcon::fromTheme("dialog-cancel").pixmap(64, 64), QString(tr("%1Wait for previous download to complete!")).arg(" ")); DMessageManager::instance()->sendMessage(this, QIcon::fromTheme("dialog-cancel").pixmap(64, 64), QString(QObject::tr("%1Wait for previous download to complete!")).arg(" "));
} }
} }
@ -405,17 +432,18 @@ void MainWindow::on_downloadFinish(QString filePath)
// 下载完成显示提示信息 // 下载完成显示提示信息
if (!isCanceled) { if (!isCanceled) {
DPushButton *button = new DPushButton(tr("Open")); DPushButton *button = new DPushButton(QObject::tr("Open"));
DFloatingMessage *message = new DFloatingMessage(DFloatingMessage::ResidentType); DFloatingMessage *message = new DFloatingMessage(DFloatingMessage::ResidentType);
message->setIcon(QIcon::fromTheme("dialog-ok").pixmap(64, 64)); message->setIcon(QIcon::fromTheme("dialog-ok").pixmap(64, 64));
message->setMessage(QString(" %1 %2 %3").arg(QFileInfo(filePath).fileName()).arg(tr("download finished.")).arg(tr("Show in file manager?"))); message->setMessage(QString(" %1 %2 %3").arg(QFileInfo(filePath).fileName()).arg(QObject::tr("download finished.")).arg(QObject::tr("Show in file manager?")));
message->setWidget(button); message->setWidget(button);
DMessageManager::instance()->sendMessage(this, message); DMessageManager::instance()->sendMessage(this, message);
connect(button, &DPushButton::clicked, this, [=]() { connect(button, &DPushButton::clicked, this, [=]() {
DDesktopServices::showFileItem(filePath); DDesktopServices::showFileItem(filePath);
message->hide(); message->hide();
message->deleteLater();
}); });
} }
} }
@ -446,5 +474,5 @@ void MainWindow::on_downloadCancel(QWebEngineDownloadItem *item)
mutex.unlock(); mutex.unlock();
downloadMessage->hide(); downloadMessage->hide();
DMessageManager::instance()->sendMessage(this, QIcon::fromTheme("dialog-error").pixmap(64, 64), QString(tr("%1Download canceled!")).arg(" ")); DMessageManager::instance()->sendMessage(this, QIcon::fromTheme("dialog-error").pixmap(64, 64), QString(QObject::tr("%1Download canceled!")).arg(" "));
} }

@ -30,11 +30,11 @@ public:
bool nFullScreen = false, bool nFullScreen = false,
bool nFixSize = false, bool nFixSize = false,
bool nHideButtons = false, bool nHideButtons = false,
QDialog *dialog = nullptr,
QWidget *parent = nullptr); QWidget *parent = nullptr);
~MainWindow(); ~MainWindow();
void setIcon(QString szIconPath); void setIcon(QString szIconPath);
void setDescription(const QString &desc);
protected: protected:
void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent *event);
@ -56,7 +56,10 @@ private:
QString saveAs(QString fileName); QString saveAs(QString fileName);
signals: signals:
void sigQuit(); void sigClose();
public slots:
void slotNewInstanceStarted();
private slots: private slots:
void on_trayIconActivated(QSystemTrayIcon::ActivationReason reason); void on_trayIconActivated(QSystemTrayIcon::ActivationReason reason);
@ -74,7 +77,6 @@ private:
bool m_isTrayEnabled, m_isFullScreen, m_isFixedSize, m_isHideButton; bool m_isTrayEnabled, m_isFullScreen, m_isFixedSize, m_isHideButton;
Widget *m_widget; Widget *m_widget;
DAboutDialog *m_dialog;
QSystemTrayIcon *m_tray; QSystemTrayIcon *m_tray;
DToolButton *btnBack; DToolButton *btnBack;

@ -7,7 +7,7 @@ TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS DEFINES += QT_DEPRECATED_WARNINGS
CONFIG += c++11 link_pkgconfig CONFIG += c++11 link_pkgconfig
PKGCONFIG += dtkwidget PKGCONFIG += dtkcore dtkgui dtkwidget
HEADERS += \ HEADERS += \
mainwindow.h \ mainwindow.h \
@ -15,14 +15,20 @@ HEADERS += \
httpd.h \ httpd.h \
httplib.h \ httplib.h \
widget.h \ widget.h \
webengineview.h webengineview.h \
webenginepage.h \
application.h \
webengineurlrequestinterceptor.h
SOURCES += \ SOURCES += \
main.cpp \ main.cpp \
httpd.cpp \ httpd.cpp \
mainwindow.cpp \ mainwindow.cpp \
widget.cpp \ widget.cpp \
webengineview.cpp webengineview.cpp \
webenginepage.cpp \
application.cpp \
webengineurlrequestinterceptor.cpp
RESOURCES += \ RESOURCES += \
imgs.qrc imgs.qrc

@ -2,200 +2,108 @@
<!DOCTYPE TS> <!DOCTYPE TS>
<TS version="2.1" language="zh_CN"> <TS version="2.1" language="zh_CN">
<context> <context>
<name>MainWindow</name> <name>DAboutDialog</name>
<message> <message>
<location filename="../mainwindow.cpp" line="41"/> <location filename="../application.cpp" line="49"/>
<source>Full Screen</source> <source>Version: %1</source>
<translation></translation> <translation>%1</translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="42"/> <location filename="../application.cpp" line="65"/>
<source>Fix Size</source> <source>%1 is released under %2</source>
<translation></translation> <translation>%1%2</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="43"/>
<source>Hide Buttons</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="44"/>
<source>Clear Cache</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="46"/>
<source>Show MainWindow</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="47"/>
<source>About</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="48"/>
<source>Exit</source>
<translation>退</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="53"/>
<source>Pause</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="54"/>
<source>Resume</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="55"/>
<source>Cancel</source>
<translation></translation>
</message>
<message>
<source>%1Fullscreen Mode</source>
<translation type="vanished">%1</translation>
</message>
<message>
<source>%1Windowed Mode</source>
<translation type="vanished">%1</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="321"/>
<source>Save As</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="376"/>
<source>%1Start downloading %2</source>
<translation>%1 %2</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="387"/>
<source>%1Wait for previous download to complete!</source>
<translation>%1</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="409"/>
<source>Open</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="413"/>
<source>download finished.</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="413"/>
<source>Show in file manager?</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="450"/>
<source>%1Download canceled!</source>
<translation>%1</translation>
</message> </message>
</context> </context>
<context> <context>
<name>QObject</name> <name>QObject</name>
<message> <message>
<location filename="../main.cpp" line="71"/> <location filename="../application.cpp" line="57"/>
<location filename="../main.cpp" line="182"/>
<source>Presented By Spark developers # HadesStudio</source> <source>Presented By Spark developers # HadesStudio</source>
<translation> @ </translation> <translation> @ </translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="63"/> <location filename="../main.cpp" line="56"/>
<source>Version:</source>
<translation></translation>
</message>
<message>
<location filename="../main.cpp" line="79"/>
<source>Published under GPLv3</source>
<translation> GPLv3 </translation>
</message>
<message>
<location filename="../main.cpp" line="83"/>
<source>Description: %1</source> <source>Description: %1</source>
<translation>%1</translation> <translation>%1</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="89"/> <location filename="../main.cpp" line="62"/>
<source>Enable CommandLineParser. Default is false.</source> <source>Enable CommandLineParser. Default is false.</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="94"/> <location filename="../main.cpp" line="67"/>
<source>The Title of Application. Default is %1.</source> <source>The Title of Application. Default is %1.</source>
<translation> %1</translation> <translation> %1</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="101"/> <location filename="../main.cpp" line="74"/>
<source>The target URL. Default is Blank.</source> <source>The target URL. Default is Blank.</source>
<translation> URL</translation> <translation> URL</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="108"/> <location filename="../main.cpp" line="81"/>
<source>The Width of Application. Default is %1.</source> <source>The Width of Application. Default is %1.</source>
<translation> %1</translation> <translation> %1</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="115"/> <location filename="../main.cpp" line="88"/>
<source>The Height of Application. Default is %1.</source> <source>The Height of Application. Default is %1.</source>
<translation> %1</translation> <translation> %1</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="122"/> <location filename="../main.cpp" line="95"/>
<source>Enable Tray Icon. Default is false.</source> <source>Enable Tray Icon. Default is false.</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="126"/> <location filename="../main.cpp" line="99"/>
<source>Run in Fullscreen Mode. Default is false.</source> <source>Run in Fullscreen Mode. Default is false.</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="130"/> <location filename="../main.cpp" line="103"/>
<source>Fix Window Size. Default is false.</source> <source>Fix Window Size. Default is false.</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="134"/> <location filename="../main.cpp" line="107"/>
<source>Hide Control Buttons. Default is false.</source> <source>Hide Control Buttons. Default is false.</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="147"/> <location filename="../main.cpp" line="112"/>
<source>The ICON of Application.</source> <source>The ICON of Application.</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="154"/> <location filename="../main.cpp" line="119"/>
<source>The Description of Application.</source> <source>The Description of Application.</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="161"/> <location filename="../main.cpp" line="126"/>
<source>The Configuration file of Application.</source> <source>The Configuration file of Application.</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="168"/> <location filename="../main.cpp" line="133"/>
<source>The root path of the program web service.</source> <source>The root path of the program web service.</source>
<translation> WebServer </translation> <translation> WebServer </translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="175"/> <location filename="../main.cpp" line="140"/>
<source>The port number of the program web service.</source> <source>The port number of the program web service.</source>
<translation> WebServer </translation> <translation> WebServer </translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="183"/> <location filename="../main.cpp" line="147"/>
<source>To use GPU instead of CPU to decoding. Default True.</source> <source>To use GPU instead of CPU to decoding. Default True.</source>
<translation>GPU渲染</translation> <translation>GPU渲染</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="191"/> <location filename="../main.cpp" line="155"/>
<source>The ssl port number of the program web service.</source> <source>The ssl port number of the program web service.</source>
<translation> WebServer SSL </translation> <translation> WebServer SSL </translation>
</message> </message>
@ -204,5 +112,93 @@
<source>SparkWebAppRuntime</source> <source>SparkWebAppRuntime</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<location filename="../mainwindow.cpp" line="43"/>
<source>Full Screen</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="44"/>
<source>Fix Size</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="45"/>
<source>Hide Buttons</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="46"/>
<source>Clear Cache</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="48"/>
<source>Show MainWindow</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="55"/>
<source>Pause</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="56"/>
<source>Resume</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="57"/>
<source>Cancel</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="339"/>
<source>Save As</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="403"/>
<source>%1Start downloading %2</source>
<translation>%1 %2</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="414"/>
<source>%1Wait for previous download to complete!</source>
<translation>%1</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="436"/>
<source>Open</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="440"/>
<source>download finished.</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="440"/>
<source>Show in file manager?</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="478"/>
<source>%1Download canceled!</source>
<translation>%1</translation>
</message>
</context>
<context>
<name>TitleBarMenu</name>
<message>
<location filename="../mainwindow.cpp" line="49"/>
<source>About</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="50"/>
<source>Exit</source>
<translation>退</translation>
</message>
</context> </context>
</TS> </TS>

@ -0,0 +1,44 @@
#include "webenginepage.h"
#include <QDesktopServices>
WebEnginePage::WebEnginePage(QObject *parent)
: QWebEnginePage(parent)
{
}
WebEnginePage::~WebEnginePage()
{
}
void WebEnginePage::setUrl(const QUrl &url)
{
if (m_currentUrl == url) {
return;
}
m_currentUrl = url;
QWebEnginePage::setUrl(url);
}
QWebEnginePage *WebEnginePage::createWindow(QWebEnginePage::WebWindowType type)
{
qDebug() << Q_FUNC_INFO << type;
WebEnginePage *page = new WebEnginePage(parent());
connect(page, &WebEnginePage::urlChanged, this, &WebEnginePage::slotUrlChanged);
return page;
}
void WebEnginePage::slotUrlChanged(const QUrl &url)
{
if (m_currentUrl == url) {
sender()->deleteLater();
return;
}
qDebug() << Q_FUNC_INFO << m_currentUrl << url;
QDesktopServices::openUrl(url);
sender()->deleteLater();
}

@ -0,0 +1,26 @@
#ifndef WEBENGINEPAGE_H
#define WEBENGINEPAGE_H
#include <QWebEnginePage>
class WebEnginePage : public QWebEnginePage
{
Q_OBJECT
public:
explicit WebEnginePage(QObject *parent = nullptr);
~WebEnginePage() override;
void setUrl(const QUrl &url);
protected:
QWebEnginePage *createWindow(WebWindowType type) override;
private slots:
void slotUrlChanged(const QUrl &url);
private:
QUrl m_currentUrl;
};
#endif // WEBENGINEPAGE_H

@ -0,0 +1,13 @@
#include "webengineurlrequestinterceptor.h"
#include <QLocale>
WebEngineUrlRequestInterceptor::WebEngineUrlRequestInterceptor(QObject *parent)
: QWebEngineUrlRequestInterceptor(parent)
{
}
void WebEngineUrlRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &info)
{
info.setHttpHeader("Accept-Language", QLocale::system().name().toUtf8());
}

@ -0,0 +1,15 @@
#ifndef WEBENGINEURLREQUESTINTERCEPTOR_H
#define WEBENGINEURLREQUESTINTERCEPTOR_H
#include <QWebEngineUrlRequestInterceptor>
class WebEngineUrlRequestInterceptor : public QWebEngineUrlRequestInterceptor
{
Q_OBJECT
public:
explicit WebEngineUrlRequestInterceptor(QObject *parent = nullptr);
void interceptRequest(QWebEngineUrlRequestInfo &info) override;
};
#endif // WEBENGINEURLREQUESTINTERCEPTOR_H

@ -1,22 +1,20 @@
#include "webengineview.h" #include "webengineview.h"
//#include "webengineurlrequestinterceptor.h"
#include <QWebEngineSettings>
#include <QWebEngineProfile>
#include <QLocale>
WebEngineView::WebEngineView(QWidget *parent) WebEngineView::WebEngineView(QWidget *parent)
: QWebEngineView(parent) : QWebEngineView(parent)
// , interceptor(new WebEngineUrlRequestInterceptor(this))
{ {
} // page()->profile()->setHttpUserAgent(page()->profile()->httpUserAgent() + " MediaFeature/prefers-color-scheme:dark");
QWebEngineView *WebEngineView::createWindow(QWebEnginePage::WebWindowType type) connect(this, &WebEngineView::urlChanged, this, [=]() {
{ // page()->setUrlRequestInterceptor(interceptor);
Q_UNUSED(type) // page()->settings()->setAttribute(QWebEngineSettings::WebAttribute::LocalContentCanAccessRemoteUrls, true);
page()->profile()->setHttpAcceptLanguage(QLocale::system().name());
QWebEngineView *view = new QWebEngineView; // qInfo() << "User Agent:" << page()->profile()->httpUserAgent();
connect(view, &QWebEngineView::urlChanged, this, &WebEngineView::on_urlChanged); });
return view;
}
void WebEngineView::on_urlChanged(QUrl url)
{
setUrl(url);
sender()->deleteLater();
} }

@ -3,6 +3,7 @@
#include <QWebEngineView> #include <QWebEngineView>
// class WebEngineUrlRequestInterceptor;
class WebEngineView : public QWebEngineView class WebEngineView : public QWebEngineView
{ {
Q_OBJECT Q_OBJECT
@ -10,12 +11,8 @@ class WebEngineView : public QWebEngineView
public: public:
explicit WebEngineView(QWidget *parent = nullptr); explicit WebEngineView(QWidget *parent = nullptr);
protected: private:
QWebEngineView *createWindow(QWebEnginePage::WebWindowType type) override; // WebEngineUrlRequestInterceptor *interceptor = nullptr;
private slots:
void on_urlChanged(QUrl url);
}; };
#endif // WEBENGINEVIEW_H #endif // WEBENGINEVIEW_H

@ -1,4 +1,10 @@
#include "widget.h" #include "widget.h"
#include "webengineview.h"
#include "webenginepage.h"
#include <DApplication>
DWIDGET_USE_NAMESPACE
Widget::Widget(QString szUrl, QWidget *parent) Widget::Widget(QString szUrl, QWidget *parent)
: QWidget(parent) : QWidget(parent)
@ -12,14 +18,16 @@ Widget::Widget(QString szUrl, QWidget *parent)
m_webEngineView->setObjectName(QStringLiteral("webEngineView")); m_webEngineView->setObjectName(QStringLiteral("webEngineView"));
m_webEngineView->setEnabled(true); m_webEngineView->setEnabled(true);
m_webEngineView->setAutoFillBackground(false); m_webEngineView->setAutoFillBackground(false);
m_webEngineView->setZoomFactor(1.0);
QWebEnginePage *page = new QWebEnginePage(m_webEngineView); DApplication *dApp = qobject_cast<DApplication *>(qApp);
m_webEngineView->setZoomFactor(dApp->devicePixelRatio());
WebEnginePage *page = new WebEnginePage(m_webEngineView);
m_webEngineView->setPage(page); m_webEngineView->setPage(page);
m_webEngineView->setUrl(QUrl(nullptr)); page->setUrl(QUrl());
if (!m_szUrl.isEmpty()) { if (!m_szUrl.isEmpty()) {
m_webEngineView->setUrl(QUrl(m_szUrl)); page->setUrl(QUrl(m_szUrl));
} }
QWidget *spinnerWidget = new QWidget(this); QWidget *spinnerWidget = new QWidget(this);
@ -40,8 +48,6 @@ Widget::Widget(QString szUrl, QWidget *parent)
Widget::~Widget() Widget::~Widget()
{ {
delete m_webEngineView;
delete m_spinner;
} }
QWebEnginePage *Widget::getPage() QWebEnginePage *Widget::getPage()

@ -1,18 +1,15 @@
#ifndef WIDGET_H #ifndef WIDGET_H
#define WIDGET_H #define WIDGET_H
#include <QWidget>
#include <QWebEngineProfile>
#include <QWebEngineView>
#include <QLayout>
#include <QStackedLayout>
#include <DSpinner> #include <DSpinner>
#include "webengineview.h" #include <QWidget>
#include <QWebEnginePage>
#include <QStackedLayout>
DWIDGET_USE_NAMESPACE DWIDGET_USE_NAMESPACE
class WebEngineView;
class Widget : public QWidget class Widget : public QWidget
{ {
Q_OBJECT Q_OBJECT
@ -26,16 +23,16 @@ public:
void goForward(); void goForward();
void refresh(); void refresh();
private:
WebEngineView *m_webEngineView;
DSpinner *m_spinner;
QStackedLayout *mainLayout;
QString m_szUrl;
private slots: private slots:
void on_loadStarted(); void on_loadStarted();
void on_loadFinished(); void on_loadFinished();
private:
WebEngineView *m_webEngineView = nullptr;
DSpinner *m_spinner = nullptr;
QStackedLayout *mainLayout = nullptr;
QString m_szUrl;
}; };
#endif // WIDGET_H #endif // WIDGET_H