plugin/fsm: add showHidden & dirs filter

This commit is contained in:
2 * r + 2 * t 2025-09-02 17:59:38 +10:00
parent 74a99d2ac4
commit dccdcd417f
2 changed files with 89 additions and 42 deletions

View file

@ -74,6 +74,21 @@ void FileSystemModel::setWatchChanges(bool watchChanges) {
update(); update();
} }
bool FileSystemModel::showHidden() const {
return m_showHidden;
}
void FileSystemModel::setShowHidden(bool showHidden) {
if (m_showHidden == showHidden) {
return;
}
m_showHidden = showHidden;
emit showHiddenChanged();
update();
}
FileSystemModel::Filter FileSystemModel::filter() const { FileSystemModel::Filter FileSystemModel::filter() const {
return m_filter; return m_filter;
} }
@ -96,8 +111,14 @@ QList<FileSystemEntry*> FileSystemModel::entries() const {
void FileSystemModel::watchDirIfRecursive(const QString& path) { void FileSystemModel::watchDirIfRecursive(const QString& path) {
if (m_recursive && m_watchChanges) { if (m_recursive && m_watchChanges) {
const auto currentDir = m_dir; const auto currentDir = m_dir;
const auto future = QtConcurrent::run([path]() { const bool showHidden = m_showHidden;
QDirIterator iter(path, QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); const auto future = QtConcurrent::run([showHidden, path]() {
QDir::Filters filters = QDir::Dirs | QDir::NoDotAndDotDot;
if (showHidden) {
filters |= QDir::Hidden;
}
QDirIterator iter(path, filters, QDirIterator::Subdirectories);
QStringList dirs; QStringList dirs;
while (iter.hasNext()) { while (iter.hasNext()) {
dirs << iter.next(); dirs << iter.next();
@ -105,10 +126,10 @@ void FileSystemModel::watchDirIfRecursive(const QString& path) {
return dirs; return dirs;
}); });
const auto watcher = new QFutureWatcher<QStringList>(this); const auto watcher = new QFutureWatcher<QStringList>(this);
connect(watcher, &QFutureWatcher<QStringList>::finished, this, [currentDir, watcher, this]() { connect(watcher, &QFutureWatcher<QStringList>::finished, this, [currentDir, showHidden, watcher, this]() {
const auto paths = watcher->result(); const auto paths = watcher->result();
if (currentDir == m_dir && !paths.isEmpty()) { if (currentDir == m_dir && showHidden == m_showHidden && !paths.isEmpty()) {
// Ignore if dir has changed // Ignore if dir or showHidden has changed
m_watcher.addPaths(paths); m_watcher.addPaths(paths);
} }
watcher->deleteLater(); watcher->deleteLater();
@ -158,58 +179,76 @@ void FileSystemModel::updateEntries() {
void FileSystemModel::updateEntriesForDir(const QString& dir) { void FileSystemModel::updateEntriesForDir(const QString& dir) {
const bool recursive = m_recursive; const bool recursive = m_recursive;
const bool showHidden = m_showHidden;
const auto filter = m_filter; const auto filter = m_filter;
const auto oldEntries = m_entries; const auto oldEntries = m_entries;
const auto baseDir = m_dir; const auto baseDir = m_dir;
const auto future = QtConcurrent::run( const auto future = QtConcurrent::run([dir, recursive, showHidden, filter, oldEntries, baseDir](
[dir, recursive, filter, oldEntries, baseDir](QPromise<QPair<QSet<QString>, QSet<QString>>>& promise) { QPromise<QPair<QSet<QString>, QSet<QString>>>& promise) {
const auto flags = recursive ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags; const auto flags = recursive ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags;
std::optional<QDirIterator> iter; std::optional<QDirIterator> iter;
if (filter == Images) { if (filter == Images) {
QStringList filters; QStringList nameFilters;
for (const auto& format : QImageReader::supportedImageFormats()) { for (const auto& format : QImageReader::supportedImageFormats()) {
filters << "*." + format; nameFilters << "*." + format;
} }
iter.emplace(dir, filters, QDir::Files, flags); QDir::Filters filters = QDir::Files;
} else if (filter == Files) { if (showHidden) {
iter.emplace(dir, QDir::Files, flags); filters |= QDir::Hidden;
}
iter.emplace(dir, nameFilters, filters, flags);
} else {
QDir::Filters filters;
if (filter == Files) {
filters = QDir::Files;
} else if (filter == Dirs) {
filters = QDir::Dirs | QDir::NoDotAndDotDot;
} else { } else {
iter.emplace(dir, QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot, flags); filters = QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot;
} }
QSet<QString> newPaths; if (showHidden) {
while (iter->hasNext()) { filters |= QDir::Hidden;
if (promise.isCanceled()) {
return;
}
QString path = iter->next();
if (filter == Images) {
QImageReader reader(path);
if (!reader.canRead()) {
continue;
}
}
newPaths.insert(path);
} }
QSet<QString> oldPaths; iter.emplace(dir, filters, flags);
for (const auto& entry : oldEntries) { }
oldPaths.insert(entry->path());
}
if (promise.isCanceled() || newPaths == oldPaths) { QSet<QString> newPaths;
while (iter->hasNext()) {
if (promise.isCanceled()) {
return; return;
} }
promise.addResult(qMakePair(oldPaths - newPaths, newPaths - oldPaths)); QString path = iter->next();
});
if (filter == Images) {
QImageReader reader(path);
if (!reader.canRead()) {
continue;
}
}
newPaths.insert(path);
}
QSet<QString> oldPaths;
for (const auto& entry : oldEntries) {
oldPaths.insert(entry->path());
}
if (promise.isCanceled() || newPaths == oldPaths) {
return;
}
promise.addResult(qMakePair(oldPaths - newPaths, newPaths - oldPaths));
});
if (m_futures.contains(dir)) { if (m_futures.contains(dir)) {
m_futures[dir].cancel(); m_futures[dir].cancel();

View file

@ -63,6 +63,7 @@ class FileSystemModel : public QAbstractListModel {
Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged) Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged)
Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged) Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged)
Q_PROPERTY(bool watchChanges READ watchChanges WRITE setWatchChanges NOTIFY watchChangesChanged) Q_PROPERTY(bool watchChanges READ watchChanges WRITE setWatchChanges NOTIFY watchChangesChanged)
Q_PROPERTY(bool showHidden READ showHidden WRITE setShowHidden NOTIFY showHiddenChanged)
Q_PROPERTY(Filter filter READ filter WRITE setFilter NOTIFY filterChanged) Q_PROPERTY(Filter filter READ filter WRITE setFilter NOTIFY filterChanged)
Q_PROPERTY(QList<FileSystemEntry*> entries READ entries NOTIFY entriesChanged) Q_PROPERTY(QList<FileSystemEntry*> entries READ entries NOTIFY entriesChanged)
@ -71,7 +72,8 @@ public:
enum Filter { enum Filter {
NoFilter, NoFilter,
Images, Images,
Files Files,
Dirs
}; };
Q_ENUM(Filter) Q_ENUM(Filter)
@ -79,6 +81,7 @@ public:
: QAbstractListModel(parent) : QAbstractListModel(parent)
, m_recursive(true) , m_recursive(true)
, m_watchChanges(true) , m_watchChanges(true)
, m_showHidden(false)
, m_filter(NoFilter) { , m_filter(NoFilter) {
connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, &FileSystemModel::watchDirIfRecursive); connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, &FileSystemModel::watchDirIfRecursive);
connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, &FileSystemModel::updateEntriesForDir); connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, &FileSystemModel::updateEntriesForDir);
@ -97,6 +100,9 @@ public:
bool watchChanges() const; bool watchChanges() const;
void setWatchChanges(bool watchChanges); void setWatchChanges(bool watchChanges);
bool showHidden() const;
void setShowHidden(bool showHidden);
Filter filter() const; Filter filter() const;
void setFilter(Filter filter); void setFilter(Filter filter);
@ -106,6 +112,7 @@ signals:
void pathChanged(); void pathChanged();
void recursiveChanged(); void recursiveChanged();
void watchChangesChanged(); void watchChangesChanged();
void showHiddenChanged();
void filterChanged(); void filterChanged();
void entriesChanged(); void entriesChanged();
@ -121,6 +128,7 @@ private:
QString m_path; QString m_path;
bool m_recursive; bool m_recursive;
bool m_watchChanges; bool m_watchChanges;
bool m_showHidden;
Filter m_filter; Filter m_filter;
void watchDirIfRecursive(const QString& path); void watchDirIfRecursive(const QString& path);