Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 141 additions & 24 deletions 3rdparty/libzipplugin/libzipplugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -545,39 +545,156 @@ PluginFinishType LibzipPlugin::addComment(const QString &comment)
return PFT_Nomral;
}

PluginFinishType LibzipPlugin::updateArchiveData(const UpdateOptions &/*options*/)
PluginFinishType LibzipPlugin::updateArchiveData(const UpdateOptions &options)
{
m_mapFileCode.clear();
m_setHasHandlesDirs.clear();
m_setHasRootDirs.clear();
DataManager::get_instance().resetArchiveData();
ArchiveData &stArchiveData = DataManager::get_instance().archiveData();
QString rootEntry;

foreach (FileEntry entry, options.listEntry) {
if (options.eType == UpdateOptions::Delete ) { // 删除,更新压缩包数据
if (entry.isDirectory) { // 删除文件夹
// 在map中查找该文件夹下的文件并删除
QMap<QString, FileEntry>::iterator itor = stArchiveData.mapFileEntry.begin();
while (itor != stArchiveData.mapFileEntry.end()) {
if (itor->strFullPath.startsWith(entry.strFullPath)) {
if (!itor->isDirectory) {
stArchiveData.qSize -= itor->qSize; // 更新压缩包内文件原始总大小
}
itor = stArchiveData.mapFileEntry.erase(itor);
} else {
++itor;
}
}

// 处理加载流程
int errcode = 0;
zip_error_t err;
// 更新文件夹第一层的数据
if (entry.strFullPath.endsWith(QLatin1Char('/')) && entry.strFullPath.count(QLatin1Char('/')) == 1) {
for (int i = 0; i < stArchiveData.listRootEntry.count(); i++) {
if (stArchiveData.listRootEntry.at(i).strFullPath == entry.strFullPath) { // 在第一次层数据中找到entry移除
stArchiveData.listRootEntry.removeAt(i);
break;
}
}
}
} else { // 删除文件
stArchiveData.qSize -= entry.qSize; // 更新压缩包内文件原始总大小
stArchiveData.mapFileEntry.remove(entry.strFullPath); //在map中删除该文件
// 更新文件夹第一层的数据
if (!entry.strFullPath.contains(QLatin1Char('/'))) {
for (int i = 0; i < stArchiveData.listRootEntry.count(); i++) {
if (stArchiveData.listRootEntry.at(i).strFullPath == entry.strFullPath) { // 在第一次层数据中找到entry移除
stArchiveData.listRootEntry.removeAt(i);
break;
}
}
}
}
} else if (options.eType == UpdateOptions::Rename) { // 重命名,更新压缩包数据
QMap<QString, FileEntry> tmpMapFileEntry;
QString strAlias;
if (entry.isDirectory) { // 重命名文件夹
// 在map中查找该文件夹下的文件并重命名
QMap<QString, FileEntry>::iterator itor = stArchiveData.mapFileEntry.begin();
while (itor != stArchiveData.mapFileEntry.end()) {
if (itor->strFullPath.startsWith(entry.strFullPath)) {
QString strPath = QFileInfo(entry.strFullPath.left(entry.strFullPath.length() - 1)).path();
if(strPath == "."){
strAlias = entry.strAlias + QDir::separator();
} else {
strAlias = strPath + QDir::separator() + entry.strAlias + QDir::separator();
}
strAlias = strAlias + QString(itor->strFullPath).right(QString(itor->strFullPath).length()-entry.strFullPath.length());
FileEntry tmpEntry = itor.value();
tmpEntry.strFullPath = strAlias;
if(tmpEntry.isDirectory) {
tmpEntry.strFileName = QFileInfo(strAlias.left(strAlias.length() - 1)).fileName();
} else {
tmpEntry.strFileName = QFileInfo(strAlias).fileName();
}
tmpEntry.strAlias.clear();
tmpMapFileEntry.insert(strAlias, tmpEntry);
itor = stArchiveData.mapFileEntry.erase(itor);
} else {
++itor;
}
}
if(!tmpMapFileEntry.isEmpty()) {
for (QString strFullPath: tmpMapFileEntry.keys()) {
stArchiveData.mapFileEntry.insert(strFullPath, tmpMapFileEntry.value(strFullPath));
}
}
// 更新文件夹第一层的数据
if (entry.strFullPath.endsWith(QLatin1Char('/')) && entry.strFullPath.count(QLatin1Char('/')) == 1) {
for (int i = 0; i < stArchiveData.listRootEntry.count(); i++) {
if (stArchiveData.listRootEntry.at(i).strFullPath == entry.strFullPath) { // 在第一次层数据中找到entry移除
stArchiveData.listRootEntry.removeAt(i);
strAlias = entry.strAlias + QDir::separator();
entry.strFullPath = strAlias;
entry.strFileName = strAlias;
stArchiveData.listRootEntry.append(entry);
Comment on lines +631 to +633

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Root-level directory rename stores strFileName as the full aliased path including the trailing separator instead of the directory basename, so the root listing displays a path-like name rather than the renamed folder name.

Triggers: When renaming a directory at the archive root.

Suggested fix: Assign QFileInfo(strAlias).fileName() (or the directory basename without the trailing separator) to entry.strFileName.

break;
}
}
}
} else { // 重命名文件
stArchiveData.mapFileEntry.remove(entry.strFullPath); //在map中重命名该文件
QString strPath = QFileInfo(entry.strFullPath).path();
if(strPath == "." || strPath.isEmpty() || strPath.isNull()) {
strAlias = entry.strAlias;
} else {
strAlias = strPath + QDir::separator() + entry.strAlias;
}
FileEntry tmpEntry = entry;
tmpEntry.strFullPath = strAlias;
stArchiveData.mapFileEntry.insert(strAlias, tmpEntry);
// 更新文件夹第一层的数据
if (!entry.strFullPath.contains(QLatin1Char('/'))) {
for (int i = 0; i < stArchiveData.listRootEntry.count(); i++) {
if (stArchiveData.listRootEntry.at(i).strFullPath == entry.strFullPath) { // 在第一次层数据中找到entry重命名
stArchiveData.listRootEntry.removeAt(i);
strAlias = entry.strAlias;
entry.strFullPath = strAlias;
entry.strFileName = strAlias;
stArchiveData.listRootEntry.append(entry);
break;
}
}
}
}
} else if (options.eType == UpdateOptions::Add) { // 追加,更新压缩包数据
QString destinationPath = options.strParentPath; // 在压缩包中追加的路径
QFileInfo file(entry.strFullPath); // 注意此时entry.strFullPath如果是是文件夹还没有'/'
if (rootEntry.isEmpty()) { // 获取所有追加文件的父目录
rootEntry = file.filePath().left(file.filePath().size() - file.fileName().size());
}

zip_t *archive = zip_open(QFile::encodeName(m_strArchiveName).constData(), ZIP_RDONLY, &errcode); // 打开压缩包文件
zip_error_init_with_code(&err, errcode);
entry.strFullPath = destinationPath + entry.strFullPath.remove(rootEntry); // entry在压缩包中的全路径
if (file.isDir()) { // 文件夹
entry.strFullPath = entry.strFullPath + QDir::separator(); // 手动添加'/'
} else {
// 更新压缩包内文件原始总大小
stArchiveData.qSize -= stArchiveData.mapFileEntry.value(entry.strFullPath).qSize;
stArchiveData.qSize += entry.qSize;
}

//某些特殊文件,如.crx用zip打不开,需要替换minizip
if (!archive) {
// m_bAllEntry = true;
// return minizip_list();
}
// 判断是否追加到第一层数据
if (destinationPath.isEmpty() && ((entry.strFullPath.count('/') == 1 && entry.strFullPath.endsWith('/')) || entry.strFullPath.count('/') == 0)) {
for (int i = 0; i < stArchiveData.listRootEntry.count(); i++) {
if (stArchiveData.listRootEntry.at(i).strFullPath == entry.strFullPath) { // 在第一层数据中找到entry,不添加数据
stArchiveData.listRootEntry.removeAt(i);
break;
}
}

// 获取文件压缩包文件数目
const auto nofEntries = zip_get_num_entries(archive, 0);
// 在第一层数据中没有找到entry,在第一层数据中添加entry
stArchiveData.listRootEntry.push_back(entry);
}

// 循环构建数据
for (zip_int64_t i = 0; i < nofEntries; i++) {
if (QThread::currentThread()->isInterruptionRequested()) {
break;
// 更新压缩包map
stArchiveData.mapFileEntry.insert(entry.strFullPath, entry);
}

handleArchiveData(archive, i); // 构建数据
}

zip_close(archive);
stArchiveData.qComressSize = QFileInfo(m_strArchiveName).size(); // 更新压缩包大小

return PFT_Nomral;
}
Expand Down
20 changes: 19 additions & 1 deletion src/source/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1556,6 +1556,7 @@ void MainWindow::handleJobNormalFinished(ArchiveJob::JobType eType, ErrorType eE
// 追加/删除更新
case ArchiveJob::JT_Update: {
qInfo() << "更新结束";
m_bInternalArchiveOperation = false;
m_pLoadingPage->stopLoading(); // 停止更新

if (DataManager::get_instance().archiveData().listRootEntry.count() == 0) {
Expand Down Expand Up @@ -1606,6 +1607,7 @@ void MainWindow::handleJobCancelFinished(ArchiveJob::JobType eType)
break;
// 添加文件至压缩包
case ArchiveJob::JT_Add: {
m_bInternalArchiveOperation = false;
//拖拽追加取消后不需要返回列表界面
if (StartupType::ST_DragDropAdd != m_eStartupType) {
m_ePageID = PI_UnCompress;
Expand Down Expand Up @@ -1650,6 +1652,13 @@ void MainWindow::handleJobCancelFinished(ArchiveJob::JobType eType)
break;
// 删除
case ArchiveJob::JT_Delete: {
m_bInternalArchiveOperation = false;
m_ePageID = PI_UnCompress;
}
break;
// 重命名
case ArchiveJob::JT_Rename: {
m_bInternalArchiveOperation = false;
m_ePageID = PI_UnCompress;
}
break;
Expand Down Expand Up @@ -1707,6 +1716,7 @@ void MainWindow::handleJobErrorFinished(ArchiveJob::JobType eJobType, ErrorType
break;
// 压缩包追加文件错误
case ArchiveJob::JT_Add: {
m_bInternalArchiveOperation = false;
//拖拽追加失败后需要跳转到失败界面,
if (StartupType::ST_DragDropAdd != m_eStartupType) {
m_ePageID = PI_UnCompress;
Expand Down Expand Up @@ -1869,6 +1879,7 @@ void MainWindow::handleJobErrorFinished(ArchiveJob::JobType eJobType, ErrorType
break;
// 删除错误
case ArchiveJob::JT_Delete: {
m_bInternalArchiveOperation = false;
m_ePageID = PI_UnCompress;
#if 0 // 删除错误提示暂时不需要
QIcon icon = UiTools::renderSVG(":assets/icons/deepin/builtin/icons/compress_fail_128px.svg", QSize(30, 30));
Expand Down Expand Up @@ -1947,7 +1958,7 @@ void MainWindow::handleJobErrorFinished(ArchiveJob::JobType eJobType, ErrorType
break;
// 更新压缩包数据错误
case ArchiveJob::JT_Update:

m_bInternalArchiveOperation = false;
break;
default:
break;
Expand Down Expand Up @@ -2003,6 +2014,7 @@ void MainWindow::addFiles2Archive(const QStringList &listFiles, const QString &s

void MainWindow::resetMainwindow()
{
m_bInternalArchiveOperation = false;
#ifdef __aarch64__
maxFileSize_ = 0;
#endif
Expand Down Expand Up @@ -2529,6 +2541,7 @@ void MainWindow::watcherArchiveFile(const QString &strFullPath)
m_pFileWatcher->startWatcher();

connect(m_pFileWatcher, &DFileWatcher::fileMoved, this, [ = ]() { //监控压缩包,重命名时提示
if (m_bInternalArchiveOperation) return;
// 取消操作
slotCancel();

Expand All @@ -2542,6 +2555,7 @@ void MainWindow::watcherArchiveFile(const QString &strFullPath)
});

connect(m_pFileWatcher, &DFileWatcher::fileDeleted, this, [ = ]() { //监控压缩包,重命名时提示
if (m_bInternalArchiveOperation) return;
QTimer::singleShot(1000, this, [=]()
{
if(QFile::exists(strFullPath)) {
Expand Down Expand Up @@ -3091,6 +3105,7 @@ void MainWindow::slotDelFiles(const QList<FileEntry> &listSelEntry, qint64 qTota
qInfo() << "删除文件:";
m_operationtype = Operation_DELETE; //提取操作
QString strArchiveFullPath = m_pUnCompressPage->archiveFullPath();
m_bInternalArchiveOperation = true;
if (ArchiveManager::get_instance()->deleteFiles(strArchiveFullPath, listSelEntry)) {
// 设置更新选项
m_stUpdateOptions.reset();
Expand Down Expand Up @@ -3144,6 +3159,7 @@ void MainWindow::slotRenameFile(const FileEntry &SelEntry, qint64 qTotalSize)
return;
}
QString strArchiveFullPath = m_pUnCompressPage->archiveFullPath();
m_bInternalArchiveOperation = true;
if (ArchiveManager::get_instance()->renameFiles(strArchiveFullPath, sListEntry)) {
// 设置更新选项
m_stUpdateOptions.reset();
Expand Down Expand Up @@ -3191,6 +3207,7 @@ void MainWindow::slotOpenFile(const FileEntry &entry, const QString &strProgram)

void MainWindow::slotOpenFileChanged(const QString &strPath)
{
if (m_bInternalArchiveOperation) return;
QMap<QString, bool> &mapStatus = m_pOpenFileWatcher->getFileHasModified();
QMap<QString, QString> mapPassword = m_pOpenFileWatcher->getFilePassword();
qInfo() << strPath;
Expand Down Expand Up @@ -3621,6 +3638,7 @@ void MainWindow::slotFinishCalculateSize(qint64 size, QString strArchiveFullPath
}
} else {
// 调用添加文件接口
m_bInternalArchiveOperation = true;
if (ArchiveManager::get_instance()->addFiles(strArchiveFullPath, listAddEntry, stOptions)) {
// 切换进度界面
m_pProgressPage->setTotalSize(size);
Expand Down
1 change: 1 addition & 0 deletions src/source/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,7 @@ private Q_SLOTS:
bool m_isFirstViewComment = true;

DFileWatcher *m_pFileWatcher = nullptr; // 文件监控
bool m_bInternalArchiveOperation = false; // 内部操作(重命名/删除/追加)进行中,抑制文件监控
QString m_strFinalConvertFile; // 格式转换最终的文件全路径
QString m_fileWriteErrorName; // 创建失败的文件名

Expand Down
Loading