#include "mainwindow-dtk.h" #include "ui_mainwindow-dtk.h" #include "utils/widgetanimation.h" #include "widgets/common/progressbutton.h" #include "widgets/downloadlistwidget.h" #include "widgets/common/downloaditem.h" #include "dbus/dbussparkstoreservice.h" #include "application.h" #include #include #include #include #include #include #include #include #include #include #include #define AppPageApplist 0 #define AppPageSearchlist 1 #define AppPageAppdetail 2 #define AppPageSettings 3 #define UploadServerUrl "https://upload.deepinos.org.cn/" MainWindow::MainWindow(QWidget *parent) : BaseWidgetOpacity(parent) , ui(new Ui::MainWindow) , downloadlistwidget(new DownloadListWidget) , trayIcon(new QSystemTrayIcon(QIcon::fromTheme("spark-store"), this)) { ui->setupUi(this); initUI(); initConnections(); initTmpDir(); ui->appintopage->setDownloadWidget(downloadlistwidget); } MainWindow::~MainWindow() { delete ui; downloadlistwidget->deleteLater(); QSettings config(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/config.ini", QSettings::IniFormat); config.setValue("window/width", width()); config.setValue("window/height", height()); config.sync(); } void MainWindow::initDbus() { DBusSparkStoreService *dbusInter = new DBusSparkStoreService(this); QDBusConnection::sessionBus().registerService("com.gitee.spark.store"); QDBusConnection::sessionBus().registerObject("/com/gitee/spark/store", "com.gitee.spark.store", this); connect(dbusInter, &DBusSparkStoreService::sigOpenUrl, this, &MainWindow::onGetUrl); } void MainWindow::onGetUrl(const QString &url) { if (url.trimmed().startsWith("spk://")) { openUrl(url); } showWindowAnimation = false; closeWindowAnimation = false; setWindowState(windowState() & Qt::WindowActive); activateWindow(); show(); } void MainWindow::onNewProcessInstance(qint64 pid, const QStringList &arguments) { Q_UNUSED(pid) onGetUrl(arguments.value(1, "")); } void MainWindow::openUrl(const QString &url) { if (url.startsWith("spk://search/")) { QString keyword = url.mid(13); if (keyword == "%") { qWarning() << "keyword '%' is not valid, which will cause QtWebEngine crash."; return; } ui->applistpage_1->getSearchList(keyword); switchPage(AppPageSearchlist); } else if (url.startsWith("spk://")) { ui->appintopage->openUrl(QUrl::fromUserInput(url)); switchPage(AppPageAppdetail); } else { QDesktopServices::openUrl(QUrl::fromUserInput(url)); } } bool MainWindow::isCloseWindowAnimation() { return closeWindowAnimation; } void MainWindow::closeEvent(QCloseEvent *event) { // 判断下载任务数量,如果没有要下载的,就直接退出主程序 if(!downloadlistwidget->isDownloadInProcess()){ // 已经全部下载完成 qApp->quit(); } BaseWidgetOpacity::closeEvent(event); } void MainWindow::changeEvent(QEvent *event) { if (event->type() != QEvent::StyleChange) { return BaseWidgetOpacity::changeEvent(event); } BaseWidgetOpacity::changeEvent(event); downloadButton->setFixedSize(searchEdit->sizeHint().height(), searchEdit->sizeHint().height()); } void MainWindow::initUI() { QSettings config(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/config.ini", QSettings::IniFormat); QSize size; size.rwidth() = config.value("window/width").toInt(); size.rheight() = config.value("window/height").toInt(); if (!size.isEmpty()) { resize(size); } // 让打开时界面显示在正中 moveToCenter(this); setWindowTitle(QObject::tr("Spark Store")); setMaskAlpha(250); initTitleBar(); initLeftMenu(); ui->stackedWidget->setCurrentIndex(0); updateUi(0); initTrayIcon(); refreshTheme(ThemeChecker::instance()->useDarkTheme()); } void MainWindow::initTitleBar() { ui->titlebar->setIcon(QIcon::fromTheme("spark-store")); ui->titlebar->setBackgroundTransparent(true); // 初始化标题栏控件 DLabel *titleLabel = new DLabel(ui->titlebar); titleLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); titleLabel->setText(tr("Spark Store")); backButton = new DPushButton(ui->titlebar); searchEdit = new DSearchEdit(ui->titlebar); searchEdit->setPlaceholderText(tr("Search or enter spk://")); searchEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); searchEdit->lineEdit()->setFixedWidth(350); downloadButton = new ProgressButton(ui->titlebar); downloadButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); downloadButton->setDownloadListWidget(downloadlistwidget); downloadButton->setFocusPolicy(Qt::FocusPolicy::ClickFocus); downloadButton->setFixedSize(searchEdit->sizeHint().height(), searchEdit->sizeHint().height()); downloadlistwidget->setFocusProxy(downloadButton); QWidget *customWidget = new QWidget(ui->titlebar); customWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); ui->titlebar->setCustomWidget(customWidget); QHBoxLayout *customWidgetLayout = new QHBoxLayout(customWidget); customWidgetLayout->setContentsMargins(8, 0, 0, 0); customWidgetLayout->setSpacing(0); customWidgetLayout->addWidget(titleLabel, 0, Qt::AlignLeft); customWidgetLayout->addSpacing(8); customWidgetLayout->addWidget(backButton, 0, Qt::AlignLeft); QWidget *centralWidget = new QWidget(customWidget); centralWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); customWidgetLayout->addWidget(centralWidget, 1, Qt::AlignHCenter); QHBoxLayout *centralLayout = new QHBoxLayout(centralWidget); centralLayout->setContentsMargins(20, 0, 10, 0); centralLayout->setSpacing(0); centralLayout->addWidget(searchEdit, 0, Qt::AlignHCenter); centralLayout->addSpacing(10); centralLayout->addWidget(downloadButton, 0, Qt::AlignHCenter); initTitleBarMenu(); backButton->setDisabled(true); downloadlistwidget->hide(); } void MainWindow::initTitleBarMenu() { QAction *actionSubmission = new QAction(tr("Submit App"), this); QAction *actionSubmissionWithClient = new QAction(tr("Submit App with client(Recommanded)"), this); QAction *setting = new QAction(tr("Settings")); QAction *upgrade = new QAction(tr("APP Upgrade and Install Settings")); QMenu *menu = new QMenu(ui->titlebar); menu->addAction(setting); menu->addAction(upgrade); menu->addAction(actionSubmission); menu->addAction(actionSubmissionWithClient); ui->titlebar->setMenu(menu); connect(actionSubmission, &QAction::triggered, this, [=] { QDesktopServices::openUrl(QUrl(UploadServerUrl)); }); connect(setting, &QAction::triggered, this, [=] { switchPage(AppPageSettings); ui->settingspage->updateUI(); }); connect(upgrade, &QAction::triggered, this, [=] { QProcess::startDetached("/opt/durapps/spark-store/bin/update-upgrade/ss-update-controler.sh", QStringList()); }); // 投稿器 connect(actionSubmissionWithClient, &QAction::triggered, this, [=] { QString submitterSpk = "spk://store/tools/spark-store-submitter"; QFile actionSubmissionClientStatus("/opt/spark-store-submitter/bin/spark-store-submitter"); if (actionSubmissionClientStatus.exists()) { qDebug() << "投稿器存在"; QProcess::startDetached("/opt/spark-store-submitter/bin/spark-store-submitter", QStringList()); } else { qDebug() << "投稿器不存在,跳转页面"; openUrl(submitterSpk); } }); } void MainWindow::initLeftMenu() { // 侧边栏按钮 foreach (QAbstractButton *button, ui->buttonGroup->buttons()) { button->setStyleSheet("QPushButton{qproperty-icon: url(data/images/userMangaer/teacher.png);}"); connect(button, &QPushButton::toggled, [=](bool checked) { if (checked == true) { searchEdit->clearEdit(); updateUi(ui->buttonGroup->buttons().indexOf(button)); } }); } } void MainWindow::initTrayIcon() { trayIcon->setToolTip(tr("Spark Store")); QMenu *menu = new QMenu(this); QAction *showAction = new QAction(QObject::tr("Show MainWindow"), menu); QAction *aboutAction = new QAction(qApp->translate("TitleBarMenu", "About"), menu); QAction *exitAction = new QAction(qApp->translate("TitleBarMenu", "Exit"), menu); menu->addAction(showAction); menu->addAction(aboutAction); menu->addAction(exitAction); trayIcon->setContextMenu(menu); connect(showAction, &QAction::triggered, this, [=]() { showWindowAnimation = false; closeWindowAnimation = false; setWindowState(windowState() & Qt::WindowActive); activateWindow(); show(); }); connect(aboutAction, &QAction::triggered, this, [=]() { qobject_cast(qApp)->handleAboutAction(); }); connect(exitAction, &QAction::triggered, this, [=]() { qobject_cast(qApp)->quit(); }); trayIcon->show(); } void MainWindow::refreshTheme(bool isDarkMode) { // 使用isDarkMode变量来判断是否是深色模式 if (isDarkMode) { //深色模式 setMaskColor(QColor("#2a2b2b")); backButton->setIcon(QIcon(":/icon/dark/back.svg")); downloadButton->setIcon(":/icon/dark/download.svg"); downloadButton->setBackgroundColor(QColor("#444444")); downloadButton->setColor(QColor("#66CCFF")); ui->pushButton_14->setIcon(QIcon(":/icon/dark/update.svg")); for (int i = 0; i < ui->buttonGroup->buttons().size(); i++) { ui->buttonGroup->buttons()[i]->setIcon(QIcon(":/icon/dark/leftbutton_" + QString::number(i) + ".svg")); if (QLocale::system().name() == "zh_CN") { ui->buttonGroup->buttons()[i]->setStyleSheet("QPushButton{background-color:transparent;}\ QPushButton:hover{background-color:#7a7a7a;border:0px;border-radius:8px;}\ QPushButton:checked{background-color:#6e6e6e;border:0px;border-radius:8px;}"); } else { ui->buttonGroup->buttons()[i]->setStyleSheet("QPushButton{background-color:transparent;text-align: left; padding-left: 15px;}\ QPushButton:hover{background-color:#7a7a7a;border:0px;border-radius:8px;text-align: left; padding-left: 15px;}\ QPushButton:checked{background-color:#6e6e6e;border:0px;border-radius:8px;text-align: left; padding-left: 15px;}"); } } } else { //亮色模式 setMaskColor(QColor("#f3f7f8")); backButton->setIcon(QIcon(":/icon/light/back.svg")); downloadButton->setBackgroundColor(QColor("#e3e4e4")); downloadButton->setColor(QColor("#66CCFF")); downloadButton->setIcon(":/icon/light/download.svg"); ui->pushButton_14->setIcon(QIcon(":/icon/light/update.svg")); for (int i = 0; i < ui->buttonGroup->buttons().size(); i++) { ui->buttonGroup->buttons()[i]->setIcon(QIcon(":/icon/light/leftbutton_" + QString::number(i) + ".svg")); if (QLocale::system().name() == "zh_CN") { ui->buttonGroup->buttons()[i]->setStyleSheet("QPushButton{background-color:transparent;}\ QPushButton:hover{background-color:#eAeAeA;border:0px;border-radius:8px;}\ QPushButton:checked{background-color:#dddddd;border:0px;border-radius:8px;}"); } else { ui->buttonGroup->buttons()[i]->setStyleSheet("QPushButton{background-color:transparent;text-align: left; padding-left: 15px;}\ QPushButton:hover{background-color:#eAeAeA;border:0px;border-radius:8px;text-align: left; padding-left: 15px;}\ QPushButton:checked{background-color:#dddddd;border:0px;border-radius:8px;text-align: left; padding-left: 15px;}"); } } } ui->pushButton_14->setStyleSheet(ui->pushButton_4->styleSheet()); ui->applistpage->setTheme(isDarkMode); ui->applistpage_1->setTheme(isDarkMode); ui->appintopage->setTheme(isDarkMode); ui->settingspage->setTheme(isDarkMode); } void MainWindow::initConnections() { // 主题切换 connect(ThemeChecker::instance(), &ThemeChecker::themeChanged, this, &MainWindow::refreshTheme); // appintopage按下下载按钮时标题栏下载列表按钮抖动 connect(ui->appintopage, &AppIntoPage::clickedDownloadBtn, [=]() { WidgetAnimation::widgetShake(downloadButton, 6); // 第一个参数是抖动的控件,第二个参数是抖动范围(像素) }); connect(backButton, &QPushButton::clicked, [=]() { ui->stackedWidget->setCurrentIndex(pageHistory.at(pageHistory.count() - 2)); pageHistory.removeLast(); if (pageHistory.count() > 1) { backButton->setEnabled(true); } else { backButton->setDisabled(true); } }); // 搜索事件 connect(searchEdit, &DSearchEdit::returnPressed, this, [=]() { QString searchtext = searchEdit->text(); if (!searchtext.isEmpty()) { if (searchtext.startsWith("spk://")) { openUrl(searchtext); searchEdit->clearEdit(); } else { if (searchtext == "%") { qWarning() << "keyword '%' matches too many results, which will cause QtWebEngine crash."; } else { ui->applistpage_1->getSearchList(searchtext); switchPage(AppPageSearchlist); } } } this->setFocus(); }); connect(downloadlistwidget, &DownloadListWidget::downloadProgress, this, [=](int i) { downloadButton->setProgress(i); }); // 列表点击事件 connect(ui->applistpage, &AppListPage::clicked, this, [=](QUrl spk) { openUrl(spk.toString()); }); connect(ui->applistpage_1, &AppListPage::clicked, this, [=](QUrl spk) { openUrl(spk.toString()); }); connect(ui->settingspage, &SettingsPage::openUrl, this, [=](QUrl spk) { openUrl(spk.toString()); }); // 托盘图标点击事件 connect(trayIcon, &QSystemTrayIcon::activated, this, [=](QSystemTrayIcon::ActivationReason reason) { switch (reason) { case QSystemTrayIcon::Trigger: { showWindowAnimation = false; closeWindowAnimation = false; setWindowState(windowState() & Qt::WindowActive); activateWindow(); show(); Q_FALLTHROUGH(); } default: break; } }); connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::newProcessInstance, this, &MainWindow::onNewProcessInstance); } void MainWindow::initTmpDir() { // 新建临时文件夹 QDir dir; dir.mkpath("/tmp/spark-store"); // 检查写入权限 QFileInfo info("/tmp/spark-store"); if (info.isWritable() == false) { auto future = QtConcurrent::run([=] { sleep(3); auto upgradeP = new QProcess(); upgradeP->startDetached("zenity", QStringList() << "--warning" << "--text" << "用户未拥有 /tmp/spark-store 写入权限,星火商店会因此工作异常,请检查!" << "--title" << "权限受限提示" << "--width" << "360" ); upgradeP->waitForStarted(); upgradeP->waitForFinished(30); upgradeP->deleteLater(); }); } } void MainWindow::switchPage(int now) // 临时方案,回家后修改 { qDebug() << pageHistory.count(); if (pageHistory.count() >= 1) { backButton->setEnabled(true); } else { backButton->setDisabled(true); } ui->stackedWidget->setCurrentIndex(now); ui->stackedWidget->currentWidget()->setFocus(); pageHistory << now; } // 刷新界面 void MainWindow::updateUi(int now) { pageHistory.clear(); QStringList itemlist; itemlist << "" << "network" << "chat" << "music" << "video" << "image_graphics" << "games" << "office" << "reading" << "development" << "tools" << "themes" << "others"; ui->applistpage->getAppList(itemlist[now]); qDebug() << itemlist[now]; switchPage(AppPageApplist); } void MainWindow::notify(QObject *receiver, QEvent *event) { if (!receiver) { return; } Dtk::Widget::DStyle *o_ptr = qobject_cast(receiver); if (o_ptr) { return; } if (receiver->inherits("QWidgetWindow") || receiver->inherits("QStyleSheetStyle")) { return; } if (event->type() == QEvent::FocusIn) { QList list = downloadButton->findChildren(QString(), Qt::FindChildrenRecursively); list << downloadlistwidget->findChildren(QString(), Qt::FindChildrenRecursively); if (receiver != downloadButton && receiver != downloadlistwidget && !list.contains(receiver)) { downloadlistwidget->hide(); } } else if (event->type() == QEvent::FocusOut) { if (!downloadlistwidget->isActiveWindow() && !isActiveWindow()) { downloadlistwidget->hide(); } } } void MainWindow::on_pushButton_14_clicked() { QString appPath; #ifdef QT_DEBUG appPath = QCoreApplication::applicationDirPath() ; QDir dir(appPath); dir.cdUp(); appPath = dir.absolutePath()+"/spark-update-tool/spark-update-tool"; qDebug() << "Spark Update Tool Path: " << appPath; if(appPath.isEmpty()) { qWarning() << "Spark Update Tool not found!"; return; } QProcess *process = new QProcess(this); QStringList arguments; arguments << appPath <<"--silent"; process->start(appPath, {"--silent"}); #else appPath = QStandardPaths::findExecutable("spark-update-tool"); QString program = "pkexec"; QStringList arguments; arguments << appPath << "--silent"; QProcess *process = new QProcess(this); process->start(program, arguments); #endif }