From f7acab6a41b6f2429529982ff604f2d233dbf838 Mon Sep 17 00:00:00 2001 From: ZhangTingan Date: Mon, 20 Jul 2026 15:20:49 +0800 Subject: [PATCH] fix: suppress rename-phase progress and reset bar before long-name extract MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two fixes for long-name ZIP extraction (PMS #370449): 1. Suppress progress emission during the 7z rn (rename) phase in handleProgress. ZipCrypto only encrypts file content, not names, so 7z rn runs without a password and reports progress — causing the bar to jump ahead before the password dialog appears. Now the rename phase is silent; real progress starts only in the extract phase. 2. Emit a progress-reset sentinel (signalprogress(-1.0)) when onLongNameProcessFinished transitions from LNE_Rename to LNE_Extract. MainWindow::slotReceiveProgress catches the negative value and calls ProgressPage::resetProgress, so the extract phase starts from 0 and the remaining-time calculation is correct instead of stuck at 00:00:01. Log: fix progress bar jump and remaining-time stuck for encrypted ZIP with long filenames Bug: https://pms.uniontech.com/bug-view-370449.html --- .../interface/archiveinterface/cliinterface.cpp | 16 ++++++++++++++++ src/source/mainwindow.cpp | 8 ++++++++ 2 files changed, 24 insertions(+) diff --git a/3rdparty/interface/archiveinterface/cliinterface.cpp b/3rdparty/interface/archiveinterface/cliinterface.cpp index 1a9e5be6..34cf0919 100644 --- a/3rdparty/interface/archiveinterface/cliinterface.cpp +++ b/3rdparty/interface/archiveinterface/cliinterface.cpp @@ -833,6 +833,15 @@ void CliInterface::deleteProcess() void CliInterface::handleProgress(const QString &line) { + // 长文件名 rename 阶段(7z rn)不向 UI 发送真实进度。 + // 原因:ZipCrypto 只加密文件内容不加密文件名,7z rn 无需密码即可运行并输出进度, + // 会导致进度条在密码框弹出前先跳一大截;而随后的 extract 阶段从 0 重新计数, + // 进度值被 ProgressPage 的单调递增逻辑丢弃,剩余时间卡死。 + // 解决:rename 阶段屏蔽进度,真实进度仅在 extract 阶段(LNE_Extract)上报。 + if (m_longNamePhase == LNE_Rename) { + return; + } + if (m_process && m_process->program().at(0).contains("7z")) { // 解析7z相关进度、文件名 int pos = line.indexOf(QLatin1Char('%')); if (pos > 1) { @@ -1557,6 +1566,13 @@ void CliInterface::onLongNameProcessFinished(int exitCode, QProcess::ExitStatus if (m_longNamePhase == LNE_Rename) { m_longNamePhase = LNE_Extract; + // rename→extract 阶段切换时重置进度条。 + // 虽然已在 handleProgress 中屏蔽了 rename 阶段的进度上报, + // 但 extractFiles 入口处可能已 emit 过 signalprogress(1), + // 且 rename 阶段可能有少量进度泄露(非 handleProgress 路径)。 + // 这里用负值作为重置哨兵,由 MainWindow::slotReceiveProgress 捕获并调用 resetProgress(), + // 确保 extract 阶段的进度从 0 开始单调递增,剩余时间计算正确。 + emit signalprogress(-1.0); QString program = m_cliProps->property("extractProgram").toString(); QStringList args = m_cliProps->extractArgs(m_longNameTempArchivePath, m_allFileList, true, m_longNamePassword); diff --git a/src/source/mainwindow.cpp b/src/source/mainwindow.cpp index 2909e8a3..bcbdd0bc 100644 --- a/src/source/mainwindow.cpp +++ b/src/source/mainwindow.cpp @@ -1228,6 +1228,14 @@ void MainWindow::slotUncompressClicked(const QString &strUncompressPath) void MainWindow::slotReceiveProgress(double dPercentage) { + // 负值是长文件名 rename→extract 阶段切换时的进度重置哨兵, + // 由 CliInterface::onLongNameProcessFinished 在 LNE_Rename→LNE_Extract 切换时发出。 + // 收到后重置进度页(进度值、剩余时间、速度、计时器),确保 extract 阶段进度从 0 开始。 + if (dPercentage < 0) { + m_pProgressPage->resetProgress(); + return; + } + if (Operation_SingleExtract == m_operationtype) { //提取删除操作使用小弹窗进度 //需要添加dPercentage < 100判断,否则会出现小文件提取进度对话框不会自动关闭 if (!m_pProgressdialog->isVisible() && dPercentage < 100 && dPercentage > 0) {