Realod folder after transfer job if it lacks file monitoring
authorLXQt Packaging Team <pkg-lxqt-devel@lists.alioth.debian.org>
Fri, 23 Oct 2020 17:28:57 +0000 (18:28 +0100)
committerDmitry Shachnev <mitya57@debian.org>
Fri, 23 Oct 2020 17:28:57 +0000 (18:28 +0100)
Closes https://github.com/lxqt/pcmanfm-qt/issues/933 and closes
https://github.com/lxqt/libfm-qt/issues/280. After a file transfer job is
finished inside a directory, if it is the path of an open folder that lacks
file monitoring, this patch reloads its corresponding folder. In this way, the
lack of file monitoring is partially compensated for.
Please note that this doesn't work with `search://` because the files inside
`search://` don't belong to it. By covering file creation, renaming, moving
from one shared folder to another and deleting after trying to move into Trash.
Last-Update: 2019-06-08

Gbp-Pq: Name workaround-missed-file-monitoring.patch

src/core/folder.cpp
src/core/folder.h
src/fileoperation.cpp
src/utilities.cpp

index adbb4808d28f6de759a501bf3e7076f2d9d332a0..01e129781677a2f05a844bf416582123075a96b8 100644 (file)
@@ -112,6 +112,20 @@ std::shared_ptr<Folder> Folder::fromPath(const FilePath& path) {
     return folder;
 }
 
+// static
+// Checks if this is the path of a folder in use.
+std::shared_ptr<Folder> Folder::findByPath(const FilePath& path) {
+    std::lock_guard<std::mutex> lock{mutex_};
+    auto it = cache_.find(path);
+    if(it != cache_.end()) {
+        auto folder = it->second.lock();
+        if(folder) {
+            return folder;
+        }
+    }
+    return nullptr;
+}
+
 bool Folder::makeDirectory(const char* /*name*/, GError** /*error*/) {
     // TODO:
     // FIXME: what the API is used for in the original libfm C API?
@@ -142,6 +156,10 @@ bool Folder::isEmpty() const {
     return files_.empty();
 }
 
+bool Folder::hasFileMonitor() const {
+    return (dirMonitor_ != nullptr);
+}
+
 FileInfoList Folder::files() const {
     FileInfoList ret;
     ret.reserve(files_.size());
index 098d21815c69a5692dc8c8036c6bfc3a123630c2..1c257e997f312f45cd99e6a17a9792035e892e8d 100644 (file)
@@ -56,6 +56,8 @@ public:
 
     static std::shared_ptr<Folder> fromPath(const FilePath& path);
 
+    static std::shared_ptr<Folder> findByPath(const FilePath& path);
+
     bool makeDirectory(const char* name, GError** error);
 
     void queryFilesystemInfo();
@@ -74,6 +76,8 @@ public:
 
     bool isEmpty() const;
 
+    bool hasFileMonitor() const;
+
     FileInfoList files() const;
 
     const FilePath& path() const;
index 5db818b21d37a87f0ed1218d7c36b00a48b25cd2..683d0927d987084581786819a1b8d9f098f4965d 100644 (file)
@@ -298,6 +298,8 @@ void FileOperation::onJobFinish() {
     }
     Q_EMIT finished();
 
+    bool tryReload = true;
+
     // special handling for trash job
     if(type_ == Trash && !job_->isCancelled()) {
         auto trashJob = static_cast<Fm::TrashJob*>(job_);
@@ -313,6 +315,26 @@ void FileOperation::onJobFinish() {
                                         "Do you want to delete them instead?")) == QMessageBox::Yes) {
                 deleteFiles(std::move(unsupportedFiles), false);
             }
+            tryReload = false;
+        }
+    }
+
+    // reload the containing folder if it is in use but does not have a file monitor
+    if(tryReload) {
+        if(!srcPaths_.empty() && (type_ == Trash || type_ == Delete || type_ == Move)) {
+            auto parent_path = srcPaths_[0].parent();
+            if(parent_path != destPath_) { // otherwise, it will be done below
+                auto folder = Fm::Folder::findByPath(parent_path);
+                if(folder && folder->isValid() && folder->isLoaded() && !folder->hasFileMonitor()) {
+                    folder->reload();
+                }
+            }
+        }
+        if(destPath_) {
+            auto folder = Fm::Folder::findByPath(destPath_);
+            if(folder && folder->isValid() && folder->isLoaded() && !folder->hasFileMonitor()) {
+                folder->reload();
+            }
         }
     }
 
index 9da7a5529892504138c87d1880792d75430f717a..18e2b2f257eedcf8c229e94045db82b413e41e57 100644 (file)
@@ -157,7 +157,8 @@ bool isCurrentPidClipboardData(const QMimeData& data) {
 }
 
 bool changeFileName(const Fm::FilePath& filePath, const QString& newName, QWidget* parent, bool showMessage) {
-    auto dest = filePath.parent().child(newName.toLocal8Bit().constData());
+    auto parent_path = filePath.parent();
+    auto dest = parent_path.child(newName.toLocal8Bit().constData());
     Fm::GErrorPtr err;
     if(!g_file_move(filePath.gfile().get(), dest.gfile().get(),
                     GFileCopyFlags(G_FILE_COPY_ALL_METADATA |
@@ -170,6 +171,13 @@ bool changeFileName(const Fm::FilePath& filePath, const QString& newName, QWidge
         }
         return false;
     }
+
+    // reload the containing folder if it is in use but does not have a file monitor
+    auto folder = Fm::Folder::findByPath(parent_path);
+    if(folder && folder->isValid() && folder->isLoaded() && !folder->hasFileMonitor()) {
+        folder->reload();
+    }
+
     return true;
 }
 
@@ -263,6 +271,12 @@ _retry:
 
         QMessageBox::critical(parent ? parent->window() : nullptr, QObject::tr("Error"), err.message());
     }
+    else { // reload the containing folder if it is in use but does not have a file monitor
+        auto folder = Fm::Folder::findByPath(parentDir);
+        if(folder && folder->isValid() && folder->isLoaded() && !folder->hasFileMonitor()) {
+            folder->reload();
+        }
+    }
 }
 
 uid_t uidFromName(QString name) {