Don't ignore creation-deletion sequences
authorTsu Jan <tsujan2000@gmail.com>
Sun, 21 Apr 2019 09:41:14 +0000 (14:11 +0430)
committerAlf Gaida <agaida@siduction.org>
Sat, 27 Apr 2019 16:40:25 +0000 (17:40 +0100)
Fixes https://github.com/lxqt/pcmanfm-qt/issues/944

Previously, if a file was in addition queue and then it came into the deletion
queue, its addition and deletion were both ignored. That was wrong and could
result in showing nonexistent files because addition can also happen in
directory list job before being processed by file info job.

Also process accumulated changes only after finishing the current info job and
don't clear all deletion paths after processing them (because, logically, only
those paths that can be deleted should be removed).

Gbp-Pq: Name dont-ignore-crea-del-sequences.patch

src/core/folder.cpp

index 813b5adf616eee5d46bd3dfda93eda9503067ae5..adbb4808d28f6de759a501bf3e7076f2d9d332a0 100644 (file)
@@ -210,16 +210,6 @@ void Folder::onFileInfoFinished() {
         return;
     }
 
-    // process the changes accumulated during this info job
-    if(filesystem_info_pending // means a pending change; see "onFileSystemInfoFinished()"
-       || !paths_to_update.empty() || !paths_to_add.empty() || !paths_to_del.empty()) {
-        QTimer::singleShot(0, this, &Folder::processPendingChanges);
-    }
-    // there's no pending change at the moment; let the next one be processed
-    else {
-        has_idle_update_handler = false;
-    }
-
     FileInfoList files_to_add;
     FileInfoList files_to_delete;
     std::vector<FileInfoPair> files_to_update;
@@ -253,6 +243,16 @@ void Folder::onFileInfoFinished() {
         Q_EMIT filesChanged(files_to_update);
     }
     Q_EMIT contentChanged();
+
+    // process the changes accumulated during this info job
+    if(filesystem_info_pending // means a pending change; see "onFileSystemInfoFinished()"
+       || !paths_to_update.empty() || !paths_to_add.empty() || !paths_to_del.empty()) {
+        QTimer::singleShot(0, this, &Folder::processPendingChanges);
+    }
+    // there's no pending change at the moment; let the next one be processed
+    else {
+        has_idle_update_handler = false;
+    }
 }
 
 void Folder::processPendingChanges() {
@@ -296,21 +296,24 @@ void Folder::processPendingChanges() {
     }
 
     // process deletion
-    if(!paths_to_del.empty()) {
-        FileInfoList deleted_files;
-        for(const auto &path: paths_to_del) {
-            auto name = path.baseName();
-            auto it = files_.find(name.get());
-            if(it != files_.end()) {
-                deleted_files.push_back(it->second);
-                files_.erase(it);
-            }
+    FileInfoList deleted_files;
+    auto path_it = paths_to_del.begin();
+    while(path_it != paths_to_del.end()) {
+        const auto& path = *path_it;
+        auto name = path.baseName();
+        auto it = files_.find(name.get());
+        if(it != files_.end()) {
+            deleted_files.push_back(it->second);
+            files_.erase(it);
+            path_it = paths_to_del.erase(path_it);
         }
-        if(!deleted_files.empty()) {
-            Q_EMIT filesRemoved(deleted_files);
-            Q_EMIT contentChanged();
+        else {
+            ++path_it;
         }
-        paths_to_del.clear();
+    }
+    if(!deleted_files.empty()) {
+        Q_EMIT filesRemoved(deleted_files);
+        Q_EMIT contentChanged();
     }
 
     if(pending_change_notify) {
@@ -386,13 +389,12 @@ void Folder::eventFileDeleted(const FilePath& path) {
     bool deleted = true;
     // qDebug() << "delete " << path.baseName().get();
     // G_LOCK(lists);
-    if(std::find(paths_to_add.cbegin(), paths_to_add.cend(), path) != paths_to_add.cend()) {
-        // if the file was going to be added, just remove it from the addition queue
-        paths_to_add.erase(std::remove(paths_to_add.begin(), paths_to_add.end(), path), paths_to_add.cend());
-    }
-    else if(std::find(paths_to_del.cbegin(), paths_to_del.cend(), path) == paths_to_del.cend()) {
+    /* WARNING: If the file is in the addition queue, we shouldn not remove it from that queue
+       and ignore its deletion because it may have been added by the directory list job, in
+       which case, ignoring an addition-deletion sequence would result in a nonexistent file. */
+    if(std::find(paths_to_del.cbegin(), paths_to_del.cend(), path) == paths_to_del.cend()) {
         paths_to_del.push_back(path);
-        // the update queue should be cancelled for a file that is going to be deleted
+        // the update queue can be cancelled for a file that is going to be deleted
         paths_to_update.erase(std::remove(paths_to_update.begin(), paths_to_update.end(), path), paths_to_update.cend());
     }
     else {