diff --git a/spark-webapp-runtime/help/help.html b/spark-webapp-runtime/help/help.html index d3affe9..6cc2913 100644 --- a/spark-webapp-runtime/help/help.html +++ b/spark-webapp-runtime/help/help.html @@ -28,6 +28,7 @@ -u, --url <url> 设置要打开的目标 URL。默认为空。 -w, --width <width> 设置应用的窗口宽度。默认为 1024。 -H, --height <height> 设置应用的窗口高度。默认为 768。 + --full-screen 以全屏模式运行。默认关闭该功能。 --fix-size 固定窗口大小。默认关闭该功能。 --hide-buttons 隐藏控制按钮。默认关闭该功能。 -i, --ico <ico> 设置应用的图标。 @@ -63,6 +64,7 @@ -u, --url <url> The target URL. Default is Blank. -w, --width <width> The Width of Application. Default is 1024. -H, --height <height> The Height of Application. Default is 768. + --full-screen Run in Fullscreen Mode. Default is false. --fix-size Fix Window Size. Default is false. --hide-buttons Hide Control Buttons. Default is false. -i, --ico <ico> The ICON of Application. diff --git a/spark-webapp-runtime/main.cpp b/spark-webapp-runtime/main.cpp index 392b13e..84cd894 100644 --- a/spark-webapp-runtime/main.cpp +++ b/spark-webapp-runtime/main.cpp @@ -86,6 +86,10 @@ int main(int argc, char *argv[]) QString::number(DEFAULT_HEIGHT)); parser.addOption(optHeight); + QCommandLineOption optFullScreen("full-screen", + QObject::tr("Run in Fullscreen Mode. Default is false.")); + parser.addOption(optFullScreen); + QCommandLineOption optFixSize("fix-size", QObject::tr("Fix Window Size. Default is false.")); parser.addOption(optFixSize); @@ -139,6 +143,7 @@ int main(int argc, char *argv[]) QString szUrl = DEFAULT_URL; int width = DEFAULT_WIDTH; int height = DEFAULT_HEIGHT; + bool fullScreen = false; bool fixSize = false; bool hideButtons = false; QString szIcon = DEFAULT_ICON; @@ -163,6 +168,7 @@ int main(int argc, char *argv[]) szUrl = settings.value("SparkWebAppRuntime/URL", DEFAULT_TITLE).toString(); width = settings.value("SparkWebAppRuntime/Width", DEFAULT_WIDTH).toUInt(); height = settings.value("SparkWebAppRuntime/Height", DEFAULT_HEIGHT).toUInt(); + fullScreen = settings.value("SparkWebAppRunTime/FullScreen", false).toBool(); fixSize = settings.value("SparkWebAppRunTime/FixSize", false).toBool(); hideButtons = settings.value("SparkWebAppRunTime/HideButtons", false).toBool(); szIcon = settings.value("SparkWebAppRuntime/Ico", DEFAULT_ICON).toString(); @@ -196,6 +202,10 @@ int main(int argc, char *argv[]) height = parser.value(optHeight).toInt(); } + if (parser.isSet(optFullScreen)) + { + fullScreen = true; + } if (parser.isSet(optFixSize)) { fixSize = true; @@ -251,38 +261,47 @@ int main(int argc, char *argv[]) if (argc > 5) { - fixSize = true; + fullScreen = true; } if (argc > 6) + { + fixSize = true; + } + if (argc > 7) { hideButtons = true; } - if (argc > 7) + if (argc > 8) { szIcon = QString(argv[7]); } - if (argc > 8) + if (argc > 9) { szDesc = QString("%1<br/><br/>%2").arg(QString(argv[8])).arg(szDefaultDesc); } - if (argc > 9) + if (argc > 10) { szRootPath = QString(argv[9]); } - if (argc > 10) + if (argc > 11) { u16Port = QString(argv[10]).toUInt(); } #if SSL_SERVER - if (argc > 11) + if (argc > 12) { u16sslPort = QString(argv[11]).toUInt(); } #endif } - MainWindow w(szTitle, szUrl, width, height, fixSize, hideButtons, dialog); + if(fixSize) + { + fullScreen = false; // 固定窗口大小时禁用全屏模式,避免标题栏按钮 BUG + } + + MainWindow w(szTitle, szUrl, width, height, fullScreen, fixSize, hideButtons, dialog); #if SSL_SERVER if (!szRootPath.isEmpty() && u16Port > 0 && u16sslPort > 0) diff --git a/spark-webapp-runtime/mainwindow.cpp b/spark-webapp-runtime/mainwindow.cpp index 8aea10f..d44baf1 100644 --- a/spark-webapp-runtime/mainwindow.cpp +++ b/spark-webapp-runtime/mainwindow.cpp @@ -3,16 +3,23 @@ #include <DMainWindow> #include <DWidgetUtil> #include <DTitlebar> +#include <DMessageManager> +#include <DPushButton> #include <QLayout> #include <QFileInfo> +#include <QFileDialog> +#include <QDir> #include <QCloseEvent> #include <QDebug> +#include "webenginepage.h" + MainWindow::MainWindow(QString szTitle, QString szUrl, int nWidth, int nHeight, + bool nFullScreen, bool nFixSize, bool nHideButtons, DAboutDialog *dialog, @@ -24,8 +31,12 @@ MainWindow::MainWindow(QString szTitle, , btnForward(new DToolButton(titlebar())) , btnRefresh(new DToolButton(titlebar())) , m_menu(new QMenu) + , m_fullScreen(new QAction("Full Screen")) , m_fixSize(new QAction(tr("Fix Size"))) , m_hideButtons(new QAction(tr("Hide Buttons"))) + , bar(new DProgressBar) + , message(new DFloatingMessage(DFloatingMessage::ResidentType)) + , process(new QProcess) , m_width(nWidth) , m_height(nHeight) { @@ -52,16 +63,23 @@ MainWindow::MainWindow(QString szTitle, titlebar()->addWidget(btnForward, Qt::AlignLeft); titlebar()->addWidget(btnRefresh, Qt::AlignLeft); + m_fullScreen->setCheckable(true); + m_fullScreen->setChecked(nFullScreen); + m_fullScreen->setDisabled(nFixSize); // 固定窗口大小时禁用全屏模式,避免标题栏按钮 BUG m_fixSize->setCheckable(true); m_fixSize->setChecked(nFixSize); - m_fixSize->setDisabled(nFixSize); // 建议使用命令行参数 --fix-size 或者 --hide-buttons 时直接禁止在 GUI 修改选项,主要因为最大化按钮无法刷新存在状态,干脆都禁用了...... + m_fixSize->setDisabled(nFixSize); m_hideButtons->setCheckable(true); m_hideButtons->setChecked(nHideButtons); m_hideButtons->setDisabled(nHideButtons); + m_menu->addAction(m_fullScreen); m_menu->addAction(m_fixSize); m_menu->addAction(m_hideButtons); titlebar()->setMenu(m_menu); + titlebar()->setAutoHideOnFullscreen(true); + + fullScreen(); fixSize(); hideButtons(); @@ -78,6 +96,10 @@ MainWindow::MainWindow(QString szTitle, m_widget->refresh(); }); + connect(m_fullScreen, &QAction::triggered, this, [=]() + { + fullScreen(); + }); connect(m_fixSize, &QAction::triggered, this, [=]() { fixSize(); @@ -86,6 +108,8 @@ MainWindow::MainWindow(QString szTitle, { hideButtons(); }); + + connect(m_widget->getPage()->profile(), &QWebEngineProfile::downloadRequested, this, &MainWindow::on_downloadStart); } MainWindow::~MainWindow() @@ -110,6 +134,20 @@ void MainWindow::setIcon(QString szIconPath) } } +void MainWindow::fullScreen() +{ + if(m_fullScreen->isChecked()) + { + showFullScreen(); + DMessageManager::instance()->sendMessage(this, QIcon::fromTheme("dialog-information").pixmap(64, 64), QString(tr("%1Fullscreen Mode")).arg(" ")); + } + else + { + showNormal(); + DMessageManager::instance()->sendMessage(this, QIcon::fromTheme("dialog-information").pixmap(64, 64), QString(tr("%1Windowed Mode")).arg(" ")); + } +} + void MainWindow::fixSize() { if(m_fixSize->isChecked()) @@ -139,8 +177,95 @@ void MainWindow::hideButtons() } } +QString MainWindow::saveAs(QString fileName) +{ + QString saveFile = QFileDialog::getSaveFileName(this, tr("Save As"), QDir::homePath() + "/Downloads/" + fileName); + if(!saveFile.isEmpty()) + { + // 判断上层目录是否可写入 + if(QFileInfo(QFileInfo(saveFile).absolutePath()).permissions().testFlag(QFile::WriteUser)) + { + return saveFile; + } + else + { + saveAs(fileName); + } + } + return nullptr; +} + +void MainWindow::keyPressEvent(QKeyEvent *event) +{ + if(m_fixSize->isEnabled()) + { + if(event->key() == Qt::Key_F11) + { + m_fullScreen->trigger(); + m_menu->update(); + } + event->accept(); + } +} + void MainWindow::closeEvent(QCloseEvent *event) { m_dialog->close(); event->accept(); } + +void MainWindow::on_downloadStart(QWebEngineDownloadItem *item) + +{ + QString fileName = QFileInfo(item->path()).fileName(); + if(saveAs(fileName).isEmpty()) + { + return; + } + item->setPath(saveAs(fileName)); + QString filePath = QFileInfo(item->path()).absoluteFilePath(); + + connect(item, &QWebEngineDownloadItem::downloadProgress, this, &MainWindow::on_downloadProgress); + connect(item, &QWebEngineDownloadItem::finished, this, [=] + { + on_downloadFinish(filePath); + }); + + DFloatingMessage *message = new DFloatingMessage(DFloatingMessage::TransientType); + message->setIcon(QIcon::fromTheme("dialog-information").pixmap(64, 64)); + message->setMessage(QString(tr("%1Start downloading %2")).arg(" ").arg(fileName)); + DMessageManager::instance()->sendMessage(this, message); + + item->accept(); +} + +void MainWindow::on_downloadProgress(qint64 bytesReceived, qint64 bytesTotal) +{ + int value = int(double(bytesReceived) / double(bytesTotal) * 100.0); + + bar->setFixedSize(250, 8); + bar->setValue(value); + message->setIcon(QIcon::fromTheme("deepin-download").pixmap(64, 64)); + message->setMessage(" " + QString::number(value) + "%"); + message->setWidget(bar); + DMessageManager::instance()->sendMessage(this, message); +} + +void MainWindow::on_downloadFinish(QString filePath) +{ + message->hide(); + + DPushButton *button = new DPushButton(tr("Open")); + + DFloatingMessage *message = new DFloatingMessage(DFloatingMessage::ResidentType); + 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->setWidget(button); + DMessageManager::instance()->sendMessage(this, message); + + connect(button, &DPushButton::clicked, this, [=] + { + process->start("dde-file-manager --show-item " + filePath); + message->hide(); + }); +} diff --git a/spark-webapp-runtime/mainwindow.h b/spark-webapp-runtime/mainwindow.h index 630db36..a808ca5 100644 --- a/spark-webapp-runtime/mainwindow.h +++ b/spark-webapp-runtime/mainwindow.h @@ -4,6 +4,10 @@ #include <DMainWindow> #include <DAboutDialog> #include <DToolButton> +#include <DProgressBar> +#include <DFloatingMessage> + +#include <QProcess> #include "widget.h" #include "globaldefine.h" @@ -19,6 +23,7 @@ public: QString szUrl = DEFAULT_URL, int nWidth = DEFAULT_WIDTH, int nHeight = DEFAULT_HEIGHT, + bool nFullScreen = false, bool nFixSize = false, bool nHideButtons = false, DAboutDialog *dialog = nullptr, @@ -36,16 +41,31 @@ private: DToolButton *btnRefresh; QMenu *m_menu; + QAction *m_fullScreen; QAction *m_fixSize; QAction *m_hideButtons; + DProgressBar *bar; + DFloatingMessage *message; + + QProcess *process; + int m_width, m_height; + void fullScreen(); void fixSize(); void hideButtons(); + QString saveAs(QString fileName); + + void keyPressEvent(QKeyEvent *event); void closeEvent(QCloseEvent *event); +private slots: + void on_downloadStart(QWebEngineDownloadItem *item); + void on_downloadProgress(qint64 bytesReceived, qint64 bytesTotal); + void on_downloadFinish(QString filePath); + signals: void sigQuit(); diff --git a/spark-webapp-runtime/translations/spark-webapp-runtime_zh_CN.ts b/spark-webapp-runtime/translations/spark-webapp-runtime_zh_CN.ts index 65e24b1..b14a0c9 100644 --- a/spark-webapp-runtime/translations/spark-webapp-runtime_zh_CN.ts +++ b/spark-webapp-runtime/translations/spark-webapp-runtime_zh_CN.ts @@ -4,15 +4,50 @@ <context> <name>MainWindow</name> <message> - <location filename="../mainwindow.cpp" line="27"/> + <location filename="../mainwindow.cpp" line="35"/> <source>Fix Size</source> <translation>固定大小</translation> </message> <message> - <location filename="../mainwindow.cpp" line="28"/> + <location filename="../mainwindow.cpp" line="36"/> <source>Hide Buttons</source> <translation>隐藏按钮</translation> </message> + <message> + <location filename="../mainwindow.cpp" line="142"/> + <source>%1Fullscreen Mode</source> + <translation>%1全屏模式</translation> + </message> + <message> + <location filename="../mainwindow.cpp" line="147"/> + <source>%1Windowed Mode</source> + <translation>%1窗口模式</translation> + </message> + <message> + <location filename="../mainwindow.cpp" line="182"/> + <source>Save As</source> + <translation>另存为</translation> + </message> + <message> + <location filename="../mainwindow.cpp" line="236"/> + <source>%1Start downloading %2</source> + <translation>%1开始下载 %2</translation> + </message> + <message> + <location filename="../mainwindow.cpp" line="258"/> + <source>Open</source> + <translation>打开</translation> + </message> + <message> + <location filename="../mainwindow.cpp" line="262"/> + <source>download finished.</source> + <translation>下载完成。</translation> + </message> + <message> + <location filename="../mainwindow.cpp" line="262"/> + <source>Show in file manager?</source> + <translation>是否在文件管理器中显示?</translation> + </message> </context> <context> <name>QObject</name> @@ -63,41 +98,46 @@ </message> <message> <location filename="../main.cpp" line="90"/> + <source>Run in Fullscreen Mode. Default is false.</source> + <translation>以全屏模式运行。默认关闭该功能。</translation> + </message> + <message> + <location filename="../main.cpp" line="94"/> <source>Fix Window Size. Default is false.</source> <translation>固定窗口大小。默认关闭该功能。</translation> </message> <message> - <location filename="../main.cpp" line="94"/> + <location filename="../main.cpp" line="98"/> <source>Hide Control Buttons. Default is false.</source> <translation>隐藏控制按钮。默认关闭该此功能。</translation> </message> <message> - <location filename="../main.cpp" line="98"/> + <location filename="../main.cpp" line="102"/> <source>The ICON of Application.</source> <translation>设置应用的图标。</translation> </message> <message> - <location filename="../main.cpp" line="104"/> + <location filename="../main.cpp" line="108"/> <source>The Description of Application.</source> <translation>设置应用的描述信息。</translation> </message> <message> - <location filename="../main.cpp" line="110"/> + <location filename="../main.cpp" line="114"/> <source>The Configuration file of Application.</source> <translation>设置应用的配置文件。</translation> </message> <message> - <location filename="../main.cpp" line="116"/> + <location filename="../main.cpp" line="120"/> <source>The root path of the program web service.</source> <translation>设置内置 WebServer 的根路径。</translation> </message> <message> - <location filename="../main.cpp" line="123"/> + <location filename="../main.cpp" line="127"/> <source>The port number of the program web service.</source> <translation>设置内置 WebServer 的监听端口号。</translation> </message> <message> - <location filename="../main.cpp" line="130"/> + <location filename="../main.cpp" line="134"/> <source>The ssl port number of the program web service.</source> <translation>设置内置 WebServer 的 SSL 协议的监听端口号。</translation> </message> @@ -107,17 +147,4 @@ <translation>星火网页应用运行环境</translation> </message> </context> -<context> - <name>WebEnginePage</name> - <message> - <location filename="../webenginepage.cpp" line="38"/> - <source>Start downloading...</source> - <translation>开始下载...</translation> - </message> - <message> - <location filename="../webenginepage.cpp" line="48"/> - <source>Download finished!</source> - <translation>下载完成!</translation> - </message> -</context> </TS> diff --git a/spark-webapp-runtime/webenginepage.cpp b/spark-webapp-runtime/webenginepage.cpp index 66e7144..29bc26e 100644 --- a/spark-webapp-runtime/webenginepage.cpp +++ b/spark-webapp-runtime/webenginepage.cpp @@ -3,18 +3,19 @@ #include <QDir> #include <QDebug> +#include <DMessageManager> + +DWIDGET_USE_NAMESPACE + WebEnginePage::WebEnginePage(QObject *parent) : QWebEnginePage(parent) - , m_profile(this->profile()) - , process(new QProcess) { - connect(m_profile, &QWebEngineProfile::downloadRequested, this, &WebEnginePage::on_download); } QWebEnginePage *WebEnginePage::createWindow(QWebEnginePage::WebWindowType type) { Q_UNUSED(type) - WebEnginePage *page = new WebEnginePage(); + WebEnginePage *page = new WebEnginePage; connect(page, &QWebEnginePage::urlChanged, this, &WebEnginePage::on_urlChanged); return page; } @@ -24,26 +25,3 @@ void WebEnginePage::on_urlChanged(const QUrl url) setUrl(url); sender()->deleteLater(); } - -void WebEnginePage::on_download(QWebEngineDownloadItem *item) - -{ - connect(item, &QWebEngineDownloadItem::downloadProgress, this, &WebEnginePage::on_downloadProgress); - connect(item, &QWebEngineDownloadItem::finished, this, &WebEnginePage::on_downloadFinished); - - // 无法指定下载位置,原因未知;默认位置为 ~/Downloads - // item->setPath(QDir::homePath() + "/Downloads/"); - item->accept(); - - process->start(QString("notify-send -a spark-webapp-runtime -t 5000 \"%1\"").arg(tr("Start downloading..."))); -} - -void WebEnginePage::on_downloadProgress(qint64 bytesReceived, qint64 bytesTotal) -{ - qDebug() << "Download Progress:\tbytesReceived: " << bytesReceived << "\tbytesTotal: " << bytesTotal; -} - -void WebEnginePage::on_downloadFinished() -{ - process->start(QString("notify-send -a spark-webapp-runtime -t 5000 \"%1\"").arg(tr("Download finished!"))); -} diff --git a/spark-webapp-runtime/webenginepage.h b/spark-webapp-runtime/webenginepage.h index 19b0df3..f36bd17 100644 --- a/spark-webapp-runtime/webenginepage.h +++ b/spark-webapp-runtime/webenginepage.h @@ -2,9 +2,7 @@ #define WEBENGINEPAGE_H #include <QWebEnginePage> -#include <QWebEngineProfile> #include <QObject> -#include <QProcess> class WebEnginePage : public QWebEnginePage { @@ -14,16 +12,8 @@ public: protected: QWebEnginePage *createWindow(WebWindowType type) override; -private: - QWebEngineProfile *m_profile; - - QProcess *process; - private slots: void on_urlChanged(const QUrl url); - void on_download(QWebEngineDownloadItem *item); - void on_downloadProgress(qint64 bytesReceived, qint64 bytesTotal); - void on_downloadFinished(); }; diff --git a/spark-webapp-runtime/widget.cpp b/spark-webapp-runtime/widget.cpp index 8e18f76..d861dc1 100644 --- a/spark-webapp-runtime/widget.cpp +++ b/spark-webapp-runtime/widget.cpp @@ -32,6 +32,11 @@ Widget::~Widget() { } +WebEnginePage *Widget::getPage() +{ + return m_page; +} + void Widget::goBack() { m_webEngineView->back(); diff --git a/spark-webapp-runtime/widget.h b/spark-webapp-runtime/widget.h index 062de66..c0748c2 100644 --- a/spark-webapp-runtime/widget.h +++ b/spark-webapp-runtime/widget.h @@ -21,6 +21,7 @@ public: explicit Widget(QString szUrl = nullptr, QWidget *parent = nullptr); ~Widget(); + WebEnginePage *getPage(); void goBack(); void goForward(); void refresh();