diff --git a/src/deb-installer/manager/packagesmanager.cpp b/src/deb-installer/manager/packagesmanager.cpp index f1b8cf29..90fcfd64 100644 --- a/src/deb-installer/manager/packagesmanager.cpp +++ b/src/deb-installer/manager/packagesmanager.cpp @@ -213,10 +213,10 @@ PackageDependsStatus PackagesManager::checkDependsStatus(const QString &package_ } } } - installWineDepends = false; // 标记wine依赖下载线程开启 - isDependsExists = false; // 标记多架构依赖冲突 - m_pair.first.clear(); // 清空available依赖 - m_pair.second.clear(); // 清空broken依赖 + GlobalStatus::setWinePreDependsInstalling(false); // mark wine dependent download thread start + isDependsExists = false; // mark multi-schema dependency conflicts + m_pair.first.clear(); // clear available dependencies + m_pair.second.clear(); // clear the broken dependency if (m_dependsPackages.contains(m_currentPkgMd5)) m_dependsPackages.remove(m_currentPkgMd5); @@ -687,13 +687,16 @@ void PackagesManager::slotDealDependResult(int iAuthRes, int iIndex, const QStri if (!m_errorIndex.contains(m_dependInstallMark[num])) m_errorIndex.insert(m_dependInstallMark[num], iAuthRes); } - if (installWineDepends) { // 下载wine依赖失败时,考虑出现依赖缺失的情况 + + // If the download of a wine dependency fails, might be the dependency is missing + if (GlobalStatus::winePreDependsInstalling()) { qInfo() << "check wine depends again !" << iIndex; getPackageDependsStatus(iIndex); if (!m_dependsPackages.isEmpty()) { qInfo() << m_dependsPackages.size() << m_dependsPackages.value(m_currentPkgMd5).second.size(); - if (m_preparedPackages.size() > 1) - installWineDepends = false; + if (m_preparedPackages.size() > 1) { + GlobalStatus::setWinePreDependsInstalling(false); + } } } emit signalEnableCloseButton(true); @@ -808,10 +811,11 @@ PackageDependsStatus PackagesManager::getPackageDependsStatus(const int index) } } } - installWineDepends = false; // 标记wine依赖下载线程开启 - isDependsExists = false; // 标记多架构依赖冲突 - m_pair.first.clear(); // 清空available依赖 - m_pair.second.clear(); // 清空broken依赖 + + GlobalStatus::setWinePreDependsInstalling(false); // mark wine dependent download thread start + isDependsExists = false; // mark multi-schema dependency conflicts + m_pair.first.clear(); // clear available dependencies + m_pair.second.clear(); // clear the broken dependency if (m_dependsPackages.contains(m_currentPkgMd5)) m_dependsPackages.remove(m_currentPkgMd5); @@ -828,8 +832,10 @@ PackageDependsStatus PackagesManager::getPackageDependsStatus(const int index) break; } - if (!m_dependInstallMark.contains(currentPackageMd5)) { // 更换判断依赖错误的标记 - installWineDepends = true; + if (!m_dependInstallMark.contains(currentPackageMd5)) { + // replace the marker that the depends error + GlobalStatus::setWinePreDependsInstalling(true); + if (!m_installWineThread->isRunning()) { m_dependInstallMark.append(currentPackageMd5); // 依赖错误的软件包的标记 更改为md5取代验证下标 qInfo() << "PackagesManager:" diff --git a/src/deb-installer/manager/packagesmanager.h b/src/deb-installer/manager/packagesmanager.h index 5a5b5ce1..5bd77fe4 100644 --- a/src/deb-installer/manager/packagesmanager.h +++ b/src/deb-installer/manager/packagesmanager.h @@ -550,8 +550,6 @@ private slots: private: AddPackageThread *m_pAddPackageThread = nullptr; // 添加包的线程 - bool installWineDepends = false; - bool isDependsExists = false; int m_validPackageCount = 0; diff --git a/src/deb-installer/model/abstract_package_list_model.h b/src/deb-installer/model/abstract_package_list_model.h index 02608ff2..2abcd22a 100644 --- a/src/deb-installer/model/abstract_package_list_model.h +++ b/src/deb-installer/model/abstract_package_list_model.h @@ -75,6 +75,8 @@ class AbstractPackageListModel : public QAbstractListModel // raw output of install/uninstall failures virtual QString lastProcessError() = 0; + // a package signature verification fails + virtual bool containsSignatureFailed() const = 0; // trigger install / uninstall Q_SLOT virtual bool slotInstallPackages() = 0; diff --git a/src/deb-installer/model/deblistmodel.cpp b/src/deb-installer/model/deblistmodel.cpp index a1a0b015..d56e2d74 100644 --- a/src/deb-installer/model/deblistmodel.cpp +++ b/src/deb-installer/model/deblistmodel.cpp @@ -11,6 +11,7 @@ #include "utils/utils.h" #include "utils/hierarchicalverify.h" #include "singleInstallerApplication.h" +#include "view/widgets/error_notify_dialog_helper.h" #include #include @@ -211,7 +212,7 @@ void DebListModel::slotDealDependResult(int authType, int dependIndex, const QSt case DebListModel::AuthDependsErr: // 安装失败后,状态的修改由debinstaller进行处理 break; case DebListModel::VerifyDependsErr: // 依赖包分级管控验证签名失败,弹出分级设置提示框 - showHierarchicalVerifyWindow(); + ErrorNotifyDialogHelper::showHierarchicalVerifyWindow(); break; default: break; @@ -322,6 +323,7 @@ bool DebListModel::slotInstallPackages() m_operatingIndex = 0; // 初始化当前操作的index m_operatingStatusIndex = 0; m_operatingPackageMd5 = m_packageMd5[m_operatingIndex]; + m_hierarchicalVerifyError = false; // start first initRowStatus(); // 初始化包的操作状态 @@ -342,6 +344,7 @@ bool DebListModel::slotUninstallPackage(int index) m_operatingPackageMd5 = m_packageMd5[m_operatingIndex]; // fix bug : 卸载失败时不提示卸载失败。 m_operatingStatusIndex = index; // 刷新操作状态的index + m_hierarchicalVerifyError = false; DebFile debFile(m_packagesManager->package(m_operatingIndex)); // 获取到包 if (!debFile.isValid()) @@ -455,6 +458,11 @@ QString DebListModel::lastProcessError() return "failed"; } +bool DebListModel::containsSignatureFailed() const +{ + return m_hierarchicalVerifyError; +} + QString DebListModel::checkPackageValid(const QString &package_path) { return m_packagesManager->checkPackageValid(QStringList(package_path)); @@ -528,12 +536,6 @@ void DebListModel::bumpInstallIndex() emit signalWorkerFinished(); // 发送安装完成信号 emit signalWholeProgressChanged(100); // 修改安装进度 emit signalCurrentPacakgeProgressChanged(100); - - // 安装结束,弹出分级管控信息提示框 - if (m_hierarchicalVerifyError) { - showHierarchicalVerifyWindow(); - m_hierarchicalVerifyError = false; - } return; } ++m_operatingStatusIndex; @@ -1558,58 +1560,6 @@ void DebListModel::showProhibitWindow() connect(Ddialog, &DDialog::rejected, exitOperate); } -/** - @brief 弹出分级管控安全等级设置引导提示窗口 - */ -void DebListModel::showHierarchicalVerifyWindow() -{ - if (!HierarchicalVerify::instance()->isValid()) { - return; - } - - DDialog *dialog = new DDialog(); - // 限制显示宽度 - dialog->setFixedWidth(380); - dialog->setFocusPolicy(Qt::TabFocus); - dialog->setModal(true); - dialog->setWindowFlag(Qt::WindowStaysOnTopHint); - - // 设置弹出窗口显示的信息 - dialog->setTitle(tr("Unable to install")); - dialog->setMessage(tr("This package does not have a valid digital signature and has been blocked from installing/running. " - "Go to Security Center > Tools > App Security to change the settings.")); - dialog->setIcon(QIcon::fromTheme("di_popwarning")); - dialog->addButton(QString(tr("Cancel", "button")), false, DDialog::ButtonNormal); - dialog->addButton(QString(tr("Proceed", "button")), true, DDialog::ButtonRecommend); - dialog->show(); - - // 拷贝自 ddialog.cpp 用于设置默认对话框高度,避免在大字号/高缩放比下显示不全,在 show() 之后调用。 - QLabel *msgLabel = dialog->findChild("MessageLabel"); - if (msgLabel) { - auto dialogStyle = dialog->style(); - if (dialogStyle) { - QSize sz = - dialogStyle->itemTextRect(msgLabel->fontMetrics(), msgLabel->rect(), Qt::TextWordWrap, false, msgLabel->text()) - .size(); - msgLabel->setMinimumHeight(qMax(sz.height(), msgLabel->sizeHint().height())); - } - } - - QPushButton *btnPorceed = qobject_cast(dialog->getButton(1)); - btnPorceed->setFocusPolicy(Qt::TabFocus); - btnPorceed->setFocus(); - - // 窗口退出操作,包括所有可以退出此窗口的操作 - std::function exitOperate = [dialog]() { dialog->deleteLater(); }; - - connect(dialog, &DDialog::finished, [dialog](int result) { - if (QDialog::Accepted == result) { - HierarchicalVerify::instance()->proceedDefenderSafetyPage(); - } - dialog->deleteLater(); - }); -} - bool DebListModel::checkBlackListApplication() { PackageDependsStatus dependsStat = m_packagesManager->getPackageDependsStatus(m_operatingIndex); diff --git a/src/deb-installer/model/deblistmodel.h b/src/deb-installer/model/deblistmodel.h index 9bc2ef35..6b4f8fc9 100644 --- a/src/deb-installer/model/deblistmodel.h +++ b/src/deb-installer/model/deblistmodel.h @@ -167,6 +167,7 @@ class DebListModel : public AbstractPackageListModel QStringList getPackageInfo(const QString &package_path) override; QString lastProcessError() override; + bool containsSignatureFailed() const override; /** * @brief checkPackageValid 查找指定包信息 @@ -399,11 +400,6 @@ private slots: */ void showProhibitWindow(); - /** - * @brief showHierarchicalVerifyWindow 弹出分级管控安全等级设置引导提示窗口 - */ - void showHierarchicalVerifyWindow(); - /** * @brief 检查当前将要安装的包是否在黑名单中。 * diff --git a/src/deb-installer/model/proxy_package_list_model.cpp b/src/deb-installer/model/proxy_package_list_model.cpp index 1bf51a77..5aa3b219 100644 --- a/src/deb-installer/model/proxy_package_list_model.cpp +++ b/src/deb-installer/model/proxy_package_list_model.cpp @@ -128,6 +128,14 @@ QString ProxyPackageListModel::lastProcessError() return errorMessage; } +bool ProxyPackageListModel::containsSignatureFailed() const +{ + auto findItr = std::find_if(m_packageModels.begin(), m_packageModels.end(), [](const ModelInfo &info) { + return info.model->containsSignatureFailed(); + }); + return findItr != m_packageModels.end(); +} + bool ProxyPackageListModel::slotInstallPackages() { if (!isWorkerPrepare()) { diff --git a/src/deb-installer/model/proxy_package_list_model.h b/src/deb-installer/model/proxy_package_list_model.h index 49287036..cc5161f4 100644 --- a/src/deb-installer/model/proxy_package_list_model.h +++ b/src/deb-installer/model/proxy_package_list_model.h @@ -27,6 +27,7 @@ class ProxyPackageListModel : public AbstractPackageListModel Pkg::DependsStatus checkDependsStatus(const QString &packagePath) override; QStringList getPackageInfo(const QString &packagePath) override; QString lastProcessError() override; + bool containsSignatureFailed() const override; Q_SLOT bool slotInstallPackages() override; Q_SLOT bool slotUninstallPackage(int index) override; diff --git a/src/deb-installer/singleInstallerApplication.cpp b/src/deb-installer/singleInstallerApplication.cpp index 9b8cf781..469d128e 100644 --- a/src/deb-installer/singleInstallerApplication.cpp +++ b/src/deb-installer/singleInstallerApplication.cpp @@ -167,7 +167,6 @@ bool SingleInstallerApplication::parseCmdLine() bIsDbus = true; } } else { - QStringList paraList = parser.positionalArguments(); for (auto it : paraList) { if (it.endsWith("ddim")) { m_ddimFiles.append(it); diff --git a/src/deb-installer/uab/uab_package.cpp b/src/deb-installer/uab/uab_package.cpp index ab655730..cb7ad46e 100644 --- a/src/deb-installer/uab/uab_package.cpp +++ b/src/deb-installer/uab/uab_package.cpp @@ -8,6 +8,11 @@ namespace Uab { +/** + * @class UabPackage + * @brief Uab package, contains package information and runtime status. + * Store version, install status, operation status, error code, and error message. + */ UabPackage::UabPackage(const UabPkgInfo::Ptr &metaPtr) : m_metaPtr(metaPtr) { @@ -21,7 +26,7 @@ const UabPkgInfo::Ptr &UabPackage::info() const bool UabPackage::isValid() const { - if (!m_metaPtr) { + if (!m_metaPtr || !fileExists()) { return false; } @@ -50,6 +55,16 @@ void UabPackage::setProcessError(Pkg::ErrorCode err, const QString &errorString) m_processError = errorString; } +bool UabPackage::fileExists() const +{ + return m_exists; +} + +void UabPackage::markNotExists() +{ + m_exists = false; +} + Pkg::DependsStatus UabPackage::dependsStatus() const { return m_dependsStatus; @@ -113,6 +128,9 @@ void UabPackage::reset() m_installedVersion.clear(); m_installStatus = Pkg::NotInstalled; + m_errorCode = Pkg::NoError; + m_processError.clear(); + if (!Uab::UabBackend::instance()->linglongExists()) { setDependsStatus(Pkg::DependsBreak); } else { diff --git a/src/deb-installer/uab/uab_package.h b/src/deb-installer/uab/uab_package.h index 09e56bac..821a996d 100644 --- a/src/deb-installer/uab/uab_package.h +++ b/src/deb-installer/uab/uab_package.h @@ -21,6 +21,8 @@ class UabPackage bool isValid() const; void setDependsStatus(Pkg::DependsStatus status); void setProcessError(Pkg::ErrorCode err, const QString &errorString); + bool fileExists() const; + void markNotExists(); Pkg::DependsStatus dependsStatus() const; Pkg::PackageInstallStatus installStatus() const; @@ -40,6 +42,8 @@ class UabPackage private: Uab::UabPkgInfo::Ptr m_metaPtr; + bool m_exists{true}; + Pkg::DependsStatus m_dependsStatus{Pkg::DependsOk}; // package's depends info Pkg::PackageInstallStatus m_installStatus{Pkg::NotInstalled}; // version check Pkg::PackageOperationStatus m_operationStatus{Pkg::Prepare}; // status for operation flow diff --git a/src/deb-installer/uab/uab_package_list_model.cpp b/src/deb-installer/uab/uab_package_list_model.cpp index c1a7566b..856a6004 100644 --- a/src/deb-installer/uab/uab_package_list_model.cpp +++ b/src/deb-installer/uab/uab_package_list_model.cpp @@ -5,20 +5,27 @@ #include "uab_package_list_model.h" #include +#include +#include +#include #include "uab_backend.h" #include "utils/utils.h" -#include - namespace Uab { static const float kCompleteProgress = 100.0; static const int kPkgInitedIndex = -1; +/** + * @class UabPackageListModel + * @brief Manage the list model of UAB packages, and handle the install and uninstall of multiple UAB packages. + * Emit execution status and error messages. + */ UabPackageListModel::UabPackageListModel(QObject *parent) : AbstractPackageListModel{parent} , m_processor(new UabProcessController(this)) + , m_fileWatcher(new QFileSystemWatcher(this)) { m_supportPackageType = Pkg::Uab; @@ -26,6 +33,8 @@ UabPackageListModel::UabPackageListModel(QObject *parent) connect(m_processor, &UabProcessController::progressChanged, this, &UabPackageListModel::slotBackendProgressChanged); connect(m_processor, &UabProcessController::processFinished, this, &UabPackageListModel::slotBackendProcessFinished); + connect(m_fileWatcher, &QFileSystemWatcher::fileChanged, this, &UabPackageListModel::slotFileChanged); + // call init uab backend while uab package list model create connect(Uab::UabBackend::instance(), &Uab::UabBackend::backendInitFinsihed, this, [this]() { if (!m_delayAppendPackages.isEmpty()) { @@ -42,10 +51,8 @@ QVariant UabPackageListModel::data(const QModelIndex &index, int role) const return {}; } - // check file exists - const UabPackage::Ptr &uabPtr = m_uabPkgList.at(index.row()); - if (!uabPtr) { + if (!uabPtr || !uabPtr->isValid()) { return {}; } @@ -104,6 +111,8 @@ void UabPackageListModel::slotAppendPackage(const QStringList &packageList) if (uabPtr && uabPtr->isValid()) { m_uabPkgList.append(uabPtr); + + m_fileWatcher->addPath(path); } } @@ -119,7 +128,10 @@ void UabPackageListModel::removePackage(int index) } if (0 <= index && index < rowCount()) { - m_uabPkgList.removeAt(index); + auto uabPtr = m_uabPkgList.takeAt(index); + if (uabPtr && uabPtr->info()) { + m_fileWatcher->removePath(uabPtr->info()->filePath); + } Q_EMIT signalPackageCountChanged(rowCount()); } @@ -198,6 +210,16 @@ QString UabPackageListModel::lastProcessError() return {}; } +bool UabPackageListModel::containsSignatureFailed() const +{ + // check if a pacakge signature verify failed. + auto findItr = std::find_if(m_uabPkgList.begin(), m_uabPkgList.end(), [](const UabPackage::Ptr &uabPtr) { + return Pkg::DigitalSignatureError == uabPtr->m_errorCode; + }); + + return findItr != m_uabPkgList.end(); +} + bool UabPackageListModel::slotInstallPackages() { if (!isWorkerPrepare() || rowCount() <= 0) { @@ -269,6 +291,12 @@ void UabPackageListModel::reset() { setWorkerStatus(WorkerPrepare); m_operatingIndex = kPkgInitedIndex; + + QStringList files = m_fileWatcher->files(); + if (!files.isEmpty()) { + m_fileWatcher->removePaths(files); + } + m_uabPkgList.clear(); } @@ -293,10 +321,10 @@ bool UabPackageListModel::installNextUab() return false; } - // check finish + // check install finish if (m_operatingIndex >= rowCount()) { - Q_EMIT signalCurrentPacakgeProgressChanged(kCompleteProgress); - Q_EMIT signalWholeProgressChanged(kCompleteProgress); + Q_EMIT signalCurrentPacakgeProgressChanged(static_cast(kCompleteProgress)); + Q_EMIT signalWholeProgressChanged(static_cast(kCompleteProgress)); setWorkerStatus(WorkerFinished); return true; @@ -344,11 +372,11 @@ void UabPackageListModel::slotBackendProgressChanged(float progress) { Q_ASSERT_X(rowCount() > 0, "check count", "row count invalid"); - float base = kCompleteProgress / rowCount(); - float wholeProgress = (m_operatingIndex + (progress / kCompleteProgress)) * base; + const float base = kCompleteProgress / rowCount(); + const float wholeProgress = (m_operatingIndex + (progress / kCompleteProgress)) * base; - Q_EMIT signalCurrentPacakgeProgressChanged(progress); - Q_EMIT signalWholeProgressChanged(wholeProgress); + Q_EMIT signalCurrentPacakgeProgressChanged(static_cast(progress)); + Q_EMIT signalWholeProgressChanged(static_cast(wholeProgress)); } void UabPackageListModel::slotBackendProcessFinished(bool success) @@ -357,11 +385,13 @@ void UabPackageListModel::slotBackendProcessFinished(bool success) // update installed status setCurrentOperation(success ? Pkg::Success : Pkg::Failed); + // update all data + Q_EMIT dataChanged(index(m_operatingIndex), index(m_operatingIndex)); // update progress - float base = kCompleteProgress / rowCount(); - Q_EMIT signalCurrentPacakgeProgressChanged(kCompleteProgress); - Q_EMIT signalWholeProgressChanged(base * (m_operatingIndex + 1)); + const float base = kCompleteProgress / rowCount(); + Q_EMIT signalCurrentPacakgeProgressChanged(static_cast(kCompleteProgress)); + Q_EMIT signalWholeProgressChanged(static_cast(base * (m_operatingIndex + 1))); switch (m_workerStatus) { case WorkerProcessing: @@ -457,4 +487,25 @@ bool UabPackageListModel::linglongExists() return true; } +void UabPackageListModel::slotFileChanged(const QString &filePath) +{ + auto findItr = std::find_if(m_uabPkgList.begin(), m_uabPkgList.end(), [&](const UabPackage::Ptr &uabPtr) { + if (uabPtr && uabPtr->isValid()) { + return uabPtr->info()->filePath == filePath; + } + return false; + }); + + if (findItr != m_uabPkgList.end()) { + const QFileInfo info((*findItr)->info()->filePath); + if (!info.exists()) { + (*findItr)->markNotExists(); + removePackage(static_cast(std::distance(findItr, m_uabPkgList.begin()))); + m_fileWatcher->removePath(filePath); + + Q_EMIT signalPackageCannotFind(info.fileName()); + } + } +} + } // namespace Uab diff --git a/src/deb-installer/uab/uab_package_list_model.h b/src/deb-installer/uab/uab_package_list_model.h index f64bf45c..ac9e4a7d 100644 --- a/src/deb-installer/uab/uab_package_list_model.h +++ b/src/deb-installer/uab/uab_package_list_model.h @@ -11,6 +11,8 @@ #include "uab_process_controller.h" #include "model/abstract_package_list_model.h" +class QFileSystemWatcher; + namespace Uab { class UabPackageListModel : public AbstractPackageListModel @@ -30,6 +32,7 @@ class UabPackageListModel : public AbstractPackageListModel Pkg::DependsStatus checkDependsStatus(const QString &packagePath) override; QStringList getPackageInfo(const QString &packagePath) override; QString lastProcessError() override; + bool containsSignatureFailed() const override; Q_SLOT bool slotInstallPackages() override; Q_SLOT bool slotUninstallPackage(int index) override; @@ -49,12 +52,16 @@ class UabPackageListModel : public AbstractPackageListModel bool packageExists(const UabPackage::Ptr &uabPtr) const; bool linglongExists(); + Q_SLOT void slotFileChanged(const QString &filePath); + private: int m_operatingIndex{-1}; QList m_uabPkgList; UabProcessController *m_processor{nullptr}; QStringList m_delayAppendPackages; // wait for backend inited. + + QFileSystemWatcher *m_fileWatcher{nullptr}; }; } // namespace Uab diff --git a/src/deb-installer/utils/hierarchicalverify.cpp b/src/deb-installer/utils/hierarchicalverify.cpp index 196885ee..3748e992 100644 --- a/src/deb-installer/utils/hierarchicalverify.cpp +++ b/src/deb-installer/utils/hierarchicalverify.cpp @@ -3,7 +3,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later #include "hierarchicalverify.h" -#include "hierarchicalverify.h" + +#include #include #include @@ -44,9 +45,9 @@ enum HierarchicalError { 安装器接收输出信息并判断是否为验签错误。 */ -HierarchicalVerify::HierarchicalVerify() { } +HierarchicalVerify::HierarchicalVerify() {} -HierarchicalVerify::~HierarchicalVerify() { } +HierarchicalVerify::~HierarchicalVerify() {} /** @return 返回分级管控签名校验辅助类实例 @@ -66,17 +67,20 @@ bool HierarchicalVerify::isValid() return false; } - bool availabled = checkHierarchicalInterface(); - if (valid != availabled) { - valid = availabled; + static std::once_flag checkFlag; + std::call_once(checkFlag, [this]() { + const bool availabled = checkHierarchicalInterface(); + if (valid != availabled) { + valid = availabled; - // 分级验签不可用时,清理当前缓存数据 - if (!valid) { - clearVerifyResult(); - } + // if the hierarchical signature verification is not available, clear cache. + if (!valid) { + clearVerifyResult(); + } - Q_EMIT validChanged(valid); - } + Q_EMIT validChanged(valid); + } + }); return valid; } diff --git a/src/deb-installer/utils/utils.cpp b/src/deb-installer/utils/utils.cpp index 8f0fd4c9..6b00912b 100644 --- a/src/deb-installer/utils/utils.cpp +++ b/src/deb-installer/utils/utils.cpp @@ -416,6 +416,22 @@ bool Utils::isDevelopMode() return kIsDevelopMode; } +/** + * @brief Mark whether the wine pre-dependency is being installed. + * Not thread-safe. + */ +static bool kWinePreDependsStatus = false; + +bool GlobalStatus::winePreDependsInstalling() +{ + return kWinePreDependsStatus; +} + +void GlobalStatus::setWinePreDependsInstalling(bool b) +{ + kWinePreDependsStatus = b; +} + DebApplicationHelper *DebApplicationHelper::instance() { static DebApplicationHelper *phelper = new DebApplicationHelper; diff --git a/src/deb-installer/utils/utils.h b/src/deb-installer/utils/utils.h index 439c94f4..63c335b6 100644 --- a/src/deb-installer/utils/utils.h +++ b/src/deb-installer/utils/utils.h @@ -75,4 +75,12 @@ class Utils : public QObject static bool isDevelopMode(); // Check if develop mode (root) }; +class GlobalStatus +{ +public: + // wine depends installing flag + static bool winePreDependsInstalling(); + static void setWinePreDependsInstalling(bool b); +}; + #endif diff --git a/src/deb-installer/view/pages/debinstaller.cpp b/src/deb-installer/view/pages/debinstaller.cpp index e015b194..e440f008 100644 --- a/src/deb-installer/view/pages/debinstaller.cpp +++ b/src/deb-installer/view/pages/debinstaller.cpp @@ -7,6 +7,7 @@ #include "model/packageanalyzer.h" #include "model/proxy_package_list_model.h" #include "view/widgets/filechoosewidget.h" +#include "view/widgets/error_notify_dialog_helper.h" #include "view/pages/multipleinstallpage.h" #include "view/pages/singleinstallpage.h" #include "view/pages/uninstallconfirmpage.h" @@ -170,7 +171,7 @@ void DebInstaller::initConnections() // During installing/uninstalling, drag is not allowed connect(m_fileListModel, &DebListModel::signalWorkerStart, this, &DebInstaller::disableCloseAndExit); - connect(m_fileListModel, &DebListModel::signalWorkerFinished, this, &DebInstaller::slotChangeDragFlag); + connect(m_fileListModel, &DebListModel::signalWorkerFinished, this, &DebInstaller::slotWorkerFinished); connect(m_fileListModel, &DebListModel::signalPackageCannotFind, this, &DebInstaller::slotShowPkgRemovedMessage); // 选择安装页面 @@ -421,6 +422,15 @@ void DebInstaller::slotShowPkgProcessBlockPage(BackendProcessPage::DisplayMode m } } +void DebInstaller::slotWorkerFinished() +{ + if (m_fileListModel->containsSignatureFailed()) { + ErrorNotifyDialogHelper::showHierarchicalVerifyWindow(); + } + + slotChangeDragFlag(); +} + void DebInstaller::disableCloseAndExit() { titlebar()->setDisableFlags(Qt::WindowCloseButtonHint); // 设置标题栏中的关闭按钮不可用 diff --git a/src/deb-installer/view/pages/debinstaller.h b/src/deb-installer/view/pages/debinstaller.h index 19224012..1cfc3062 100644 --- a/src/deb-installer/view/pages/debinstaller.h +++ b/src/deb-installer/view/pages/debinstaller.h @@ -243,6 +243,9 @@ private slots: */ void slotShowPkgProcessBlockPage(BackendProcessPage::DisplayMode mode, int currentRate, int pkgCount); + // install / unisntall finished + void slotWorkerFinished(); + private: /** * @brief initUI diff --git a/src/deb-installer/view/pages/multipleinstallpage.cpp b/src/deb-installer/view/pages/multipleinstallpage.cpp index 86aac783..3262b37a 100644 --- a/src/deb-installer/view/pages/multipleinstallpage.cpp +++ b/src/deb-installer/view/pages/multipleinstallpage.cpp @@ -338,8 +338,7 @@ void MultipleInstallPage::initConnections() QVariant data = m_debListModel->data(index, AbstractPackageListModel::PackageDependsDetailRole); auto depends = data.value(); - // TODO: implement later - slotDependPackages(depends, false); + slotDependPackages(depends, GlobalStatus::winePreDependsInstalling()); }); } diff --git a/src/deb-installer/view/pages/singleinstallpage.cpp b/src/deb-installer/view/pages/singleinstallpage.cpp index 9982525e..21ed8070 100644 --- a/src/deb-installer/view/pages/singleinstallpage.cpp +++ b/src/deb-installer/view/pages/singleinstallpage.cpp @@ -779,8 +779,7 @@ void SingleInstallPage::slotRefreshSinglePackageDepends() QVariant data = m_packagesModel->data(index, AbstractPackageListModel::PackageDependsDetailRole); auto depends = data.value(); - // TODO: implement later - slotDependPackages(depends, false); + slotDependPackages(depends, GlobalStatus::winePreDependsInstalling()); } } diff --git a/src/deb-installer/view/widgets/error_notify_dialog_helper.cpp b/src/deb-installer/view/widgets/error_notify_dialog_helper.cpp new file mode 100644 index 00000000..b0c096a4 --- /dev/null +++ b/src/deb-installer/view/widgets/error_notify_dialog_helper.cpp @@ -0,0 +1,76 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "error_notify_dialog_helper.h" + +#include +#include +#include + +#include + +#include "utils/hierarchicalverify.h" + +DWIDGET_USE_NAMESPACE + +static const int kDefaultDialogWidth = 380; + +/** + * @class ErrorNotifyDialogHelper + * @brief A helper class to show the error notify dialog. + */ +ErrorNotifyDialogHelper::ErrorNotifyDialogHelper(QObject *parent) + : QObject{parent} +{ +} + +void ErrorNotifyDialogHelper::showHierarchicalVerifyWindow() +{ + if (!HierarchicalVerify::instance()->isValid()) { + return; + } + + DDialog *dialog = new DDialog(); + // limit the display width + dialog->setFixedWidth(kDefaultDialogWidth); + dialog->setFocusPolicy(Qt::TabFocus); + dialog->setModal(true); + dialog->setWindowFlag(Qt::WindowStaysOnTopHint); + + // set the information displayed by the pop-up window + dialog->setTitle(QObject::tr("Unable to install")); + dialog->setMessage( + QObject::tr("This package does not have a valid digital signature and has been blocked from installing/running. " + "Go to Security Center > Tools > App Security to change the settings.")); + dialog->setIcon(QIcon::fromTheme("di_popwarning")); + dialog->addButton(QObject::tr("Cancel", "button"), false, DDialog::ButtonNormal); + dialog->addButton(QObject::tr("Proceed", "button"), true, DDialog::ButtonRecommend); + dialog->show(); + + // Copy from ddialog.cpp, used to set the default dialog height. + // Avoid incomplete display at large font size/high zoom ratio, called after show(). + auto *msgLabel = dialog->findChild("MessageLabel"); + if (msgLabel) { + auto *dialogStyle = dialog->style(); + if (dialogStyle) { + const QSize sz = + dialogStyle->itemTextRect(msgLabel->fontMetrics(), msgLabel->rect(), Qt::TextWordWrap, false, msgLabel->text()) + .size(); + msgLabel->setMinimumHeight(qMax(sz.height(), msgLabel->sizeHint().height())); + } + } + + auto *btnPorceed = qobject_cast(dialog->getButton(1)); + if (btnPorceed) { + btnPorceed->setFocusPolicy(Qt::TabFocus); + btnPorceed->setFocus(); + } + + connect(dialog, &DDialog::finished, [dialog](int result) { + if (QDialog::Accepted == result) { + HierarchicalVerify::instance()->proceedDefenderSafetyPage(); + } + dialog->deleteLater(); + }); +} diff --git a/src/deb-installer/view/widgets/error_notify_dialog_helper.h b/src/deb-installer/view/widgets/error_notify_dialog_helper.h new file mode 100644 index 00000000..3b3f4d92 --- /dev/null +++ b/src/deb-installer/view/widgets/error_notify_dialog_helper.h @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef ERROR_NOTIFY_DIALOG_HELPER_H +#define ERROR_NOTIFY_DIALOG_HELPER_H + +#include + +// popup error dialogs, support deb / uab packages +class ErrorNotifyDialogHelper : public QObject +{ + Q_OBJECT +public: + explicit ErrorNotifyDialogHelper(QObject *parent = nullptr); + ~ErrorNotifyDialogHelper() override = default; + + static void showHierarchicalVerifyWindow(); + +private: + Q_DISABLE_COPY_MOVE(ErrorNotifyDialogHelper); +}; + +#endif // ERROR_NOTIFY_DIALOG_HELPER_H diff --git a/tests/src/manager/ut_packagemanager.cpp b/tests/src/manager/ut_packagemanager.cpp index 312fab9c..92cae430 100644 --- a/tests/src/manager/ut_packagemanager.cpp +++ b/tests/src/manager/ut_packagemanager.cpp @@ -10,6 +10,7 @@ #include "../deb-installer/manager/AddPackageThread.h" #include "../deb-installer/model/deblistmodel.h" #include "../deb-installer/model/packageanalyzer.h" +#include "../deb-installer/utils/utils.h" #include #include @@ -875,7 +876,8 @@ TEST_F(UT_packagesManager, PackageManager_UT_packageInstallStatus_01) m_packageManager->appendPackage({"/1"}); ASSERT_EQ(m_packageManager->packageInstallStatus(0), 0); - ASSERT_EQ(Pkg::PackageInstallStatus::NotInstalled, m_packageManager->m_packageInstallStatus[m_packageManager->m_packageMd5.value(0)]); + ASSERT_EQ(Pkg::PackageInstallStatus::NotInstalled, + m_packageManager->m_packageInstallStatus[m_packageManager->m_packageMd5.value(0)]); } TEST_F(UT_packagesManager, PackageManager_UT_packageInstallStatus_02) @@ -987,13 +989,13 @@ TEST_F(UT_packagesManager, PackageManager_UT_DealDependResult) m_packageManager->slotDealDependResult(5, 0, ""); EXPECT_EQ(Pkg::DependsStatus::DependsBreak, m_packageManager->m_packageMd5DependsStatus[m_packageManager->m_dependInstallMark[0]].status); - m_packageManager->installWineDepends = true; + GlobalStatus::setWinePreDependsInstalling(true); m_packageManager->slotDealDependResult(5, 0, ""); EXPECT_EQ(Pkg::DependsStatus::DependsBreak, m_packageManager->m_packageMd5DependsStatus[m_packageManager->m_dependInstallMark[0]].status); m_packageManager->m_preparedPackages.append({"1", "2"}); m_packageManager->slotDealDependResult(5, 0, ""); - EXPECT_FALSE(m_packageManager->installWineDepends); + EXPECT_FALSE(GlobalStatus::winePreDependsInstalling()); EXPECT_EQ(Pkg::DependsStatus::DependsBreak, m_packageManager->m_packageMd5DependsStatus[m_packageManager->m_dependInstallMark[0]].status); } diff --git a/tests/src/model/ut_deblistmodel.cpp b/tests/src/model/ut_deblistmodel.cpp index bcb1f03e..cfc8189b 100644 --- a/tests/src/model/ut_deblistmodel.cpp +++ b/tests/src/model/ut_deblistmodel.cpp @@ -10,6 +10,7 @@ #include "../deb-installer/utils/utils.h" #include "../deb-installer/utils/result.h" #include "../deb-installer/utils/hierarchicalverify.h" +#include "../deb-installer/view/widgets/error_notify_dialog_helper.h" #include @@ -858,7 +859,8 @@ TEST_F(ut_DebListModel_test, deblistmodel_UT_DealDependResult) TEST_F(ut_DebListModel_test, deblistmodel_UT_DealDependResult_VerifyDependsErr) { Stub tmpStub; - tmpStub.set(ADDR(DebListModel, showHierarchicalVerifyWindow), stub_DebListModel_showHierarchicalVerifyWindow_DoNothing); + tmpStub.set(ADDR(ErrorNotifyDialogHelper, showHierarchicalVerifyWindow), + stub_DebListModel_showHierarchicalVerifyWindow_DoNothing); g_VerifyDeependErrCount = 0; m_debListModel->slotDealDependResult(DebListModel::VerifyDependsErr, 0, ""); @@ -895,7 +897,7 @@ TEST_F(ut_DebListModel_test, deblistmodel_UT_bumpInstallIndex) EXPECT_EQ("", m_debListModel->m_operatingPackageMd5); } -TEST_F(ut_DebListModel_test, deblistmodel_UT_bumpInstallIndex_showHierarchicalVerifyWindow) +TEST_F(ut_DebListModel_test, deblistmodel_UT_slotInstallPackages_resetHierarchicalVerify) { stub.set(ADDR(DebListModel, installNextDeb), model_installNextDeb); m_debListModel->m_operatingIndex = 0; @@ -903,12 +905,7 @@ TEST_F(ut_DebListModel_test, deblistmodel_UT_bumpInstallIndex_showHierarchicalVe m_debListModel->m_packageMd5.append("1"); m_debListModel->m_hierarchicalVerifyError = true; - Stub tmpStub; - tmpStub.set(ADDR(DebListModel, showHierarchicalVerifyWindow), stub_DebListModel_showHierarchicalVerifyWindow_DoNothing); - - g_VerifyDeependErrCount = 0; - m_debListModel->bumpInstallIndex(); - EXPECT_EQ(g_VerifyDeependErrCount, 1); + m_debListModel->slotInstallPackages(); EXPECT_FALSE(m_debListModel->m_hierarchicalVerifyError); }