From 6beccb0fd3ff70b6bb1883f0d34cd28f858d7ab2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E4=B8=8A=E8=A1=8CRyer?= Date: Tue, 29 Aug 2023 12:14:54 +0800 Subject: [PATCH] fix: file/dir name codec error (#354) current method to resolve path is not corret due to encoding issues, simply using QDir/QFileInfo to replace std::filesystem and std::string. --- .../directorymanager/directorymanager.cpp | 91 ++++++++----------- qimgv/components/loader/loaderrunnable.cpp | 1 + qimgv/sourcecontainers/fsentry.cpp | 32 +++---- qimgv/sourcecontainers/fsentry.h | 5 +- 4 files changed, 57 insertions(+), 72 deletions(-) diff --git a/qimgv/components/directorymanager/directorymanager.cpp b/qimgv/components/directorymanager/directorymanager.cpp index 896cb2d6..999044ea 100644 --- a/qimgv/components/directorymanager/directorymanager.cpp +++ b/qimgv/components/directorymanager/directorymanager.cpp @@ -1,5 +1,8 @@ #include "directorymanager.h" +#include +#include + namespace fs = std::filesystem; DirectoryManager::DirectoryManager() : @@ -320,64 +323,45 @@ void DirectoryManager::loadEntryList(QString directoryPath, bool recursive) { // both directories & files void DirectoryManager::addEntriesFromDirectory(std::vector &entryVec, QString directoryPath) { - QRegularExpressionMatch match; - for(const auto & entry : fs::directory_iterator(toStdString(directoryPath))) { - QString name = QString::fromStdString(entry.path().filename().generic_string()); + QDir root(directoryPath); + root.setFilter(QDir::Dirs | QDir::Files #ifndef Q_OS_WIN32 - // ignore hidden files - if(name.startsWith(".")) - continue; + | QDir::NoDot #endif - QString path = QString::fromStdString(entry.path().generic_string()); - match = regex.match(name); - if(entry.is_directory()) { // this can still throw std::bad_alloc .. - FSEntry newEntry; - try { - newEntry.name = name; - newEntry.path = path; - newEntry.isDirectory = true; - //newEntry.size = entry.file_size(); - //newEntry.modifyTime = entry.last_write_time(); - } catch (const std::filesystem::filesystem_error &err) { - qDebug() << "[DirectoryManager]" << err.what(); - continue; - } + ); + + QRegularExpressionMatch match{}; + for (const auto &entry : root.entryInfoList()) { + match = regex.match(entry.absoluteFilePath()); + if (!entry.isDir() && !match.hasMatch()) { continue; } + FSEntry newEntry{}; + newEntry.name = entry.fileName(); + newEntry.path = entry.absoluteFilePath(); + newEntry.isDirectory = entry.isDir(); + if (newEntry.isDirectory) { dirEntryVec.emplace_back(newEntry); - } else if (match.hasMatch()) { - FSEntry newEntry; - try { - newEntry.name = name; - newEntry.path = path; - newEntry.isDirectory = false; - newEntry.size = entry.file_size(); - newEntry.modifyTime = entry.last_write_time(); - } catch (const std::filesystem::filesystem_error &err) { - qDebug() << "[DirectoryManager]" << err.what(); - continue; - } + } else { + newEntry.size = entry.size(); + newEntry.modifyTime = entry.lastModified(); entryVec.emplace_back(newEntry); } } } void DirectoryManager::addEntriesFromDirectoryRecursive(std::vector &entryVec, QString directoryPath) { - QRegularExpressionMatch match; - for(const auto & entry : fs::recursive_directory_iterator(toStdString(directoryPath))) { - QString name = QString::fromStdString(entry.path().filename().generic_string()); - QString path = QString::fromStdString(entry.path().generic_string()); - match = regex.match(name); - if(!entry.is_directory() && match.hasMatch()) { - FSEntry newEntry; - try { - newEntry.name = name; - newEntry.path = path; - newEntry.isDirectory = false; - newEntry.size = entry.file_size(); - newEntry.modifyTime = entry.last_write_time(); - } catch (const std::filesystem::filesystem_error &err) { - qDebug() << "[DirectoryManager]" << err.what(); - continue; - } + QDir root(directoryPath); + root.setFilter(QDir::Files); + + QRegularExpressionMatch match{}; + for (const auto &entry : root.entryInfoList()) { + match = regex.match(entry.absoluteFilePath()); + if (match.hasMatch()) { + FSEntry newEntry{}; + newEntry.name = entry.fileName(); + newEntry.path = entry.absoluteFilePath(); + newEntry.isDirectory = entry.isDir(); + newEntry.size = entry.size(); + newEntry.modifyTime = entry.lastModified(); entryVec.emplace_back(newEntry); } } @@ -417,9 +401,8 @@ bool DirectoryManager::insertFileEntry(const QString &filePath) { bool DirectoryManager::forceInsertFileEntry(const QString &filePath) { if(!this->isFile(filePath) || containsFile(filePath)) return false; - std::filesystem::directory_entry stdEntry(toStdString(filePath)); - QString fileName = QString::fromStdString(stdEntry.path().filename().generic_string()); // isn't it beautiful - FSEntry FSEntry(filePath, fileName, stdEntry.file_size(), stdEntry.last_write_time(), stdEntry.is_directory()); + QFileInfo file(filePath); + FSEntry FSEntry(file.absoluteFilePath(), file.fileName(), file.size(), file.lastModified(), file.isDir()); insert_sorted(fileEntryVec, FSEntry, std::bind(compareFunction(), this, std::placeholders::_1, std::placeholders::_2)); if(!directoryPath().isEmpty()) { qDebug() << "fileIns" << filePath << directoryPath(); @@ -471,8 +454,8 @@ void DirectoryManager::renameFileEntry(const QString &oldFilePath, const QString int oldIndex = indexOfFile(oldFilePath); fileEntryVec.erase(fileEntryVec.begin() + oldIndex); // insert - std::filesystem::directory_entry stdEntry(toStdString(newFilePath)); - FSEntry FSEntry(newFilePath, newFileName, stdEntry.file_size(), stdEntry.last_write_time(), stdEntry.is_directory()); + QFileInfo file(newFilePath); + FSEntry FSEntry(file.absoluteFilePath(), file.fileName(), file.size(), file.lastModified(), file.isDir()); insert_sorted(fileEntryVec, FSEntry, std::bind(compareFunction(), this, std::placeholders::_1, std::placeholders::_2)); qDebug() << "fileRen" << oldFilePath << newFilePath; emit fileRenamed(oldFilePath, oldIndex, newFilePath, indexOfFile(newFilePath)); diff --git a/qimgv/components/loader/loaderrunnable.cpp b/qimgv/components/loader/loaderrunnable.cpp index 3293733d..3d0a2af9 100644 --- a/qimgv/components/loader/loaderrunnable.cpp +++ b/qimgv/components/loader/loaderrunnable.cpp @@ -8,6 +8,7 @@ LoaderRunnable::LoaderRunnable(QString _path) : path(_path) { void LoaderRunnable::run() { //QElapsedTimer t; //t.start(); + qDebug() << "Loading " << path; auto image = ImageFactory::createImage(path); //qDebug() << "L: " << t.elapsed(); emit finished(image, path); diff --git a/qimgv/sourcecontainers/fsentry.cpp b/qimgv/sourcecontainers/fsentry.cpp index 6d483bee..ff004693 100644 --- a/qimgv/sourcecontainers/fsentry.cpp +++ b/qimgv/sourcecontainers/fsentry.cpp @@ -1,29 +1,26 @@ #include "fsentry.h" +#include + FSEntry::FSEntry() { } FSEntry::FSEntry(const QString &path) { - std::filesystem::directory_entry stdEntry(toStdString(path)); - QString name = QString::fromStdString(stdEntry.path().filename().generic_string()); - if(stdEntry.is_directory()) { - try { - this->name = name; - this->path = path; - this->isDirectory = true; - } catch (const std::filesystem::filesystem_error &err) { } + QFileInfo file(path); + if(file.isDir()) { + this->name = file.fileName(); + this->path = file.absoluteFilePath(); + this->isDirectory = true; } else { - try { - this->name = name; - this->path = path; - this->isDirectory = false; - this->size = stdEntry.file_size(); - this->modifyTime = stdEntry.last_write_time(); - } catch (const std::filesystem::filesystem_error &err) { } + this->name = file.fileName(); + this->path = file.absoluteFilePath(); + this->isDirectory = false; + this->size = file.size(); + this->modifyTime = file.lastModified(); } } -FSEntry::FSEntry( QString _path, QString _name, std::uintmax_t _size, std::filesystem::file_time_type _modifyTime, bool _isDirectory) +FSEntry::FSEntry( QString _path, QString _name, std::uintmax_t _size, QDateTime _modifyTime, bool _isDirectory) : path(_path), name(_name), size(_size), @@ -31,6 +28,7 @@ FSEntry::FSEntry( QString _path, QString _name, std::uintmax_t _size, std::files isDirectory(_isDirectory) { } + FSEntry::FSEntry( QString _path, QString _name, std::uintmax_t _size, bool _isDirectory) : path(_path), name(_name), @@ -38,12 +36,14 @@ FSEntry::FSEntry( QString _path, QString _name, std::uintmax_t _size, bool _isDi isDirectory(_isDirectory) { } + FSEntry::FSEntry( QString _path, QString _name, bool _isDirectory) : path(_path), name(_name), isDirectory(_isDirectory) { } + bool FSEntry::operator==(const QString &anotherPath) const { return this->path == anotherPath; } diff --git a/qimgv/sourcecontainers/fsentry.h b/qimgv/sourcecontainers/fsentry.h index 521d6815..d53a3513 100644 --- a/qimgv/sourcecontainers/fsentry.h +++ b/qimgv/sourcecontainers/fsentry.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include #include "utils/stuff.h" @@ -7,13 +8,13 @@ class FSEntry { public: FSEntry(); FSEntry( const QString &filePath); - FSEntry( QString _path, QString _name, std::uintmax_t _size, std::filesystem::file_time_type _modifyTime, bool _isDirectory); + FSEntry( QString _path, QString _name, std::uintmax_t _size, QDateTime _modifyTime, bool _isDirectory); FSEntry( QString _path, QString _name, std::uintmax_t _size, bool _isDirectory); FSEntry( QString _path, QString _name, bool _isDirectory); bool operator==(const QString &anotherPath) const; QString path, name; std::uintmax_t size; - std::filesystem::file_time_type modifyTime; + QDateTime modifyTime; bool isDirectory; };