diff options
| author | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-09-03 00:21:36 +1000 |
|---|---|---|
| committer | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-09-03 00:21:36 +1000 |
| commit | 7b35c23bd0d2e4ce1e3a30a8953669762e409972 (patch) | |
| tree | 8d5bc75a09186c8b0596645a545a6b47a896fdda /plugin/src | |
| parent | lock/notifs: fix undef error (diff) | |
| download | caelestia-shell-7b35c23bd0d2e4ce1e3a30a8953669762e409972.tar.gz caelestia-shell-7b35c23bd0d2e4ce1e3a30a8953669762e409972.tar.bz2 caelestia-shell-7b35c23bd0d2e4ce1e3a30a8953669762e409972.zip | |
plugin/fsm: incremental updates
Diffstat (limited to '')
| -rw-r--r-- | plugin/src/Caelestia/filesystemmodel.cpp | 107 | ||||
| -rw-r--r-- | plugin/src/Caelestia/filesystemmodel.hpp | 2 |
2 files changed, 87 insertions, 22 deletions
diff --git a/plugin/src/Caelestia/filesystemmodel.cpp b/plugin/src/Caelestia/filesystemmodel.cpp index 3f75303..7f973a0 100644 --- a/plugin/src/Caelestia/filesystemmodel.cpp +++ b/plugin/src/Caelestia/filesystemmodel.cpp @@ -266,38 +266,101 @@ void FileSystemModel::updateEntriesForDir(const QString& dir) { } const auto result = watcher->result(); - const auto removedPaths = result.first; - const auto addedPaths = result.second; + applyChanges(result.first, result.second); - beginResetModel(); + watcher->deleteLater(); + }); + + watcher->setFuture(future); +} + +void FileSystemModel::applyChanges(const QSet<QString>& removedPaths, const QSet<QString>& addedPaths) { + QList<int> removedIndices; + for (int i = 0; i < m_entries.size(); ++i) { + if (removedPaths.contains(m_entries[i]->path())) { + removedIndices << i; + } + } + std::sort(removedIndices.begin(), removedIndices.end(), std::greater<int>()); - const int numEntries = static_cast<int>(m_entries.size()); - for (int i = numEntries - 1; i >= 0; --i) { - if (removedPaths.contains(m_entries[i]->path())) { + int start = -1; + int end = -1; + for (int idx : removedIndices) { + if (start == -1) { + start = idx; + end = idx; + } else if (idx == end - 1) { + end = idx; + } else { + beginRemoveRows(QModelIndex(), end, start); + for (int i = start; i >= end; --i) { emit removed(m_entries[i]->path()); delete m_entries.takeAt(i); } - } + endRemoveRows(); - for (const auto& path : addedPaths) { - const auto entry = new FileSystemEntry(path, m_dir.relativeFilePath(path), this); - emit added(entry); - m_entries << entry; + start = idx; + end = idx; } + } + if (start != -1) { + beginRemoveRows(QModelIndex(), end, start); + for (int i = start; i >= end; --i) { + emit removed(m_entries[i]->path()); + delete m_entries.takeAt(i); + } + endRemoveRows(); + } - std::sort(m_entries.begin(), m_entries.end(), [](const FileSystemEntry* a, const FileSystemEntry* b) { - if (a->isDir() != b->isDir()) { - return a->isDir(); - } - return a->relativePath().localeAwareCompare(b->relativePath()) < 0; - }); + QList<FileSystemEntry*> newEntries; + for (const auto& path : addedPaths) { + newEntries << new FileSystemEntry(path, m_dir.relativeFilePath(path), this); + } + std::sort(newEntries.begin(), newEntries.end(), &FileSystemModel::compareEntries); - emit entriesChanged(); + int insertStart = -1; + int prevRow = -1; + QList<FileSystemEntry*> batchItems; + for (const auto& entry : newEntries) { + const auto it = std::lower_bound(m_entries.begin(), m_entries.end(), entry, &FileSystemModel::compareEntries); + int row = static_cast<int>(it - m_entries.begin()); - endResetModel(); + if (insertStart == -1) { + insertStart = row; + prevRow = row; + batchItems.clear(); + batchItems << entry; + } else if (row == prevRow + 1) { + prevRow = row; + batchItems << entry; + } else { + beginInsertRows(QModelIndex(), insertStart, static_cast<int>(insertStart + batchItems.size() - 1)); + for (int i = 0; i < batchItems.size(); ++i) { + m_entries.insert(insertStart + i, batchItems[i]); + emit added(batchItems[i]); + } + endInsertRows(); - watcher->deleteLater(); - }); + insertStart = row; + prevRow = row; + batchItems.clear(); + batchItems << entry; + } + prevRow = static_cast<int>(m_entries.indexOf(entry)); + } + if (!batchItems.isEmpty()) { + beginInsertRows(QModelIndex(), insertStart, static_cast<int>(insertStart + batchItems.size() - 1)); + for (int i = 0; i < batchItems.size(); ++i) { + m_entries.insert(insertStart + i, batchItems[i]); + emit added(batchItems[i]); + } + endInsertRows(); + } +} - watcher->setFuture(future); +bool FileSystemModel::compareEntries(const FileSystemEntry* a, const FileSystemEntry* b) { + if (a->isDir() != b->isDir()) { + return a->isDir(); + } + return a->relativePath().localeAwareCompare(b->relativePath()) < 0; } diff --git a/plugin/src/Caelestia/filesystemmodel.hpp b/plugin/src/Caelestia/filesystemmodel.hpp index fdcd6c1..2e3bf93 100644 --- a/plugin/src/Caelestia/filesystemmodel.hpp +++ b/plugin/src/Caelestia/filesystemmodel.hpp @@ -154,4 +154,6 @@ private: void updateWatcher(); void updateEntries(); void updateEntriesForDir(const QString& dir); + void applyChanges(const QSet<QString>& removedPaths, const QSet<QString>& addedPaths); + static bool compareEntries(const FileSystemEntry* a, const FileSystemEntry* b); }; |