plugin/fsm: fix crash

Fixes #663
Fixes #681
Fixes #647

also build dev plugin with RelWithDebInfo
This commit is contained in:
2 * r + 2 * t 2025-09-24 12:17:26 +10:00
parent 2ccd3a8662
commit e294adf96a
4 changed files with 14 additions and 31 deletions

2
.envrc
View file

@ -9,7 +9,7 @@ watch_file plugin/**/*.cpp
watch_file plugin/**/*.hpp watch_file plugin/**/*.hpp
watch_file **/CMakeLists.txt watch_file **/CMakeLists.txt
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=clazy -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DDISTRIBUTOR=direnv cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_CXX_COMPILER=clazy -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DDISTRIBUTOR=direnv
cmake --build build cmake --build build
export CAELESTIA_LIB_DIR="$PWD/build/lib" export CAELESTIA_LIB_DIR="$PWD/build/lib"
export QML2_IMPORT_PATH="$PWD/build/qml:${QML2_IMPORT_PATH:-}" export QML2_IMPORT_PATH="$PWD/build/qml:${QML2_IMPORT_PATH:-}"

View file

@ -266,14 +266,11 @@ void FileSystemModel::updateWatcher() {
void FileSystemModel::updateEntries() { void FileSystemModel::updateEntries() {
if (m_path.isEmpty()) { if (m_path.isEmpty()) {
if (!m_entries.isEmpty()) { if (!m_entries.isEmpty()) {
auto toDelete = m_entries;
beginResetModel(); beginResetModel();
qDeleteAll(m_entries);
m_entries.clear(); m_entries.clear();
endResetModel(); endResetModel();
emit entriesChanged(); emit entriesChanged();
qDeleteAll(toDelete);
} }
return; return;
@ -396,8 +393,7 @@ void FileSystemModel::applyChanges(const QSet<QString>& removedPaths, const QSet
} }
std::sort(removedIndices.begin(), removedIndices.end(), std::greater<int>()); std::sort(removedIndices.begin(), removedIndices.end(), std::greater<int>());
QList<FileSystemEntry*> toDelete; // Batch remove old entries
int start = -1; int start = -1;
int end = -1; int end = -1;
for (int idx : std::as_const(removedIndices)) { for (int idx : std::as_const(removedIndices)) {
@ -409,8 +405,7 @@ void FileSystemModel::applyChanges(const QSet<QString>& removedPaths, const QSet
} else { } else {
beginRemoveRows(QModelIndex(), end, start); beginRemoveRows(QModelIndex(), end, start);
for (int i = start; i >= end; --i) { for (int i = start; i >= end; --i) {
emit removed(m_entries[i]->path()); m_entries.takeAt(i)->deleteLater();
toDelete << m_entries.takeAt(i);
} }
endRemoveRows(); endRemoveRows();
@ -421,12 +416,12 @@ void FileSystemModel::applyChanges(const QSet<QString>& removedPaths, const QSet
if (start != -1) { if (start != -1) {
beginRemoveRows(QModelIndex(), end, start); beginRemoveRows(QModelIndex(), end, start);
for (int i = start; i >= end; --i) { for (int i = start; i >= end; --i) {
emit removed(m_entries[i]->path()); m_entries.takeAt(i)->deleteLater();
toDelete << m_entries.takeAt(i);
} }
endRemoveRows(); endRemoveRows();
} }
// Create new entries
QList<FileSystemEntry*> newEntries; QList<FileSystemEntry*> newEntries;
for (const auto& path : addedPaths) { for (const auto& path : addedPaths) {
newEntries << new FileSystemEntry(path, m_dir.relativeFilePath(path), this); newEntries << new FileSystemEntry(path, m_dir.relativeFilePath(path), this);
@ -435,57 +430,50 @@ void FileSystemModel::applyChanges(const QSet<QString>& removedPaths, const QSet
return compareEntries(a, b); return compareEntries(a, b);
}); });
// Batch insert new entries
int insertStart = -1; int insertStart = -1;
int prevRow = -1;
QList<FileSystemEntry*> batchItems; QList<FileSystemEntry*> batchItems;
for (const auto& entry : std::as_const(newEntries)) { for (const auto& entry : std::as_const(newEntries)) {
const auto it = std::lower_bound( const auto it = std::lower_bound(
m_entries.begin(), m_entries.end(), entry, [this](const FileSystemEntry* a, const FileSystemEntry* b) { m_entries.begin(), m_entries.end(), entry, [this](const FileSystemEntry* a, const FileSystemEntry* b) {
return compareEntries(a, b); return compareEntries(a, b);
}); });
int row = static_cast<int>(it - m_entries.begin()); const auto row = static_cast<int>(it - m_entries.begin());
if (insertStart == -1) { if (insertStart == -1) {
insertStart = row; insertStart = row;
prevRow = row;
batchItems.clear();
batchItems << entry; batchItems << entry;
} else if (row == prevRow + 1) { } else if (row == insertStart + batchItems.size()) {
prevRow = row;
batchItems << entry; batchItems << entry;
} else { } else {
beginInsertRows(QModelIndex(), insertStart, static_cast<int>(insertStart + batchItems.size() - 1)); beginInsertRows(QModelIndex(), insertStart, insertStart + static_cast<int>(batchItems.size()) - 1);
for (int i = 0; i < batchItems.size(); ++i) { for (int i = 0; i < batchItems.size(); ++i) {
m_entries.insert(insertStart + i, batchItems[i]); m_entries.insert(insertStart + i, batchItems[i]);
emit added(batchItems[i]);
} }
endInsertRows(); endInsertRows();
insertStart = row; insertStart = row;
prevRow = row;
batchItems.clear(); batchItems.clear();
batchItems << entry; batchItems << entry;
} }
prevRow = static_cast<int>(m_entries.indexOf(entry));
} }
if (!batchItems.isEmpty()) { if (!batchItems.isEmpty()) {
beginInsertRows(QModelIndex(), insertStart, static_cast<int>(insertStart + batchItems.size() - 1)); beginInsertRows(QModelIndex(), insertStart, insertStart + static_cast<int>(batchItems.size()) - 1);
for (int i = 0; i < batchItems.size(); ++i) { for (int i = 0; i < batchItems.size(); ++i) {
m_entries.insert(insertStart + i, batchItems[i]); m_entries.insert(insertStart + i, batchItems[i]);
emit added(batchItems[i]);
} }
endInsertRows(); endInsertRows();
} }
emit entriesChanged(); emit entriesChanged();
qDeleteAll(toDelete);
} }
bool FileSystemModel::compareEntries(const FileSystemEntry* a, const FileSystemEntry* b) const { bool FileSystemModel::compareEntries(const FileSystemEntry* a, const FileSystemEntry* b) const {
if (a->isDir() != b->isDir()) { if (a->isDir() != b->isDir()) {
return m_sortReverse ^ a->isDir(); return m_sortReverse ^ a->isDir();
} }
return m_sortReverse ^ (a->relativePath().localeAwareCompare(b->relativePath()) < 0); const auto cmp = a->relativePath().localeAwareCompare(b->relativePath());
return m_sortReverse ? cmp > 0 : cmp < 0;
} }
} // namespace caelestia } // namespace caelestia

View file

@ -121,9 +121,6 @@ signals:
void nameFiltersChanged(); void nameFiltersChanged();
void entriesChanged(); void entriesChanged();
void added(const caelestia::FileSystemEntry* entry);
void removed(const QString& path);
private: private:
QDir m_dir; QDir m_dir;
QFileSystemWatcher m_watcher; QFileSystemWatcher m_watcher;

View file

@ -207,18 +207,16 @@ void AppDb::updateApps() {
newIds.insert(entry->property("id").toString()); newIds.insert(entry->property("id").toString());
} }
QList<AppEntry*> toDelete;
for (auto it = m_apps.keyBegin(); it != m_apps.keyEnd(); ++it) { for (auto it = m_apps.keyBegin(); it != m_apps.keyEnd(); ++it) {
const auto& id = *it; const auto& id = *it;
if (!newIds.contains(id)) { if (!newIds.contains(id)) {
dirty = true; dirty = true;
toDelete << m_apps.take(id); m_apps.take(id)->deleteLater();
} }
} }
if (dirty) { if (dirty) {
emit appsChanged(); emit appsChanged();
qDeleteAll(toDelete);
} }
} }