Socket API: add an option to replace existing files with virtual files
authorOlivier Goffart <ogoffart@woboq.com>
Tue, 28 Aug 2018 08:35:26 +0000 (10:35 +0200)
committerKevin Ottens <kevin.ottens@nextcloud.com>
Tue, 15 Dec 2020 09:58:06 +0000 (10:58 +0100)
Issue #6726

src/gui/socketapi.cpp
src/gui/socketapi.h

index 3f222e949eaf1dda9043bffddde8b95336ac6726..22e88e05e99fafb753315a60d0ae2b43063a9f7d 100644 (file)
@@ -702,6 +702,41 @@ void SocketApi::command_DOWNLOAD_VIRTUAL_FILE(const QString &filesArg, SocketLis
     }
 }
 
+/* Go over all the files ans replace them by a virtual file */
+void SocketApi::command_REPLACE_VIRTUAL_FILE(const QString &filesArg, SocketListener *)
+{
+    QStringList files = filesArg.split(QLatin1Char('\x1e')); // Record Separator
+    auto suffix = QStringLiteral(APPLICATION_DOTVIRTUALFILE_SUFFIX);
+
+    for (const auto &file : files) {
+        auto folder = FolderMan::instance()->folderForPath(file);
+        if (!folder)
+            continue;
+        if (file.endsWith(suffix))
+            continue;
+        QString relativePath = QDir::cleanPath(file).mid(folder->cleanPath().length() + 1);
+        QFileInfo fi(file);
+        if (fi.isDir()) {
+            folder->journalDb()->getFilesBelowPath(relativePath.toUtf8(), [&](const SyncJournalFileRecord &rec) {
+                if (rec._type != ItemTypeFile || rec._path.endsWith(APPLICATION_DOTVIRTUALFILE_SUFFIX))
+                    return;
+                QString file = folder->path() + '/' + QString::fromUtf8(rec._path);
+                if (!FileSystem::rename(file, file + suffix)) {
+                    qCWarning(lcSocketApi) << "Unable to rename " << file;
+                }
+            });
+            continue;
+        }
+        SyncJournalFileRecord record;
+        if (!folder->journalDb()->getFileRecord(relativePath, &record) || !record.isValid())
+            continue;
+        if (!FileSystem::rename(file, file + suffix)) {
+            qCWarning(lcSocketApi) << "Unable to rename " << file;
+        }
+        FolderMan::instance()->scheduleFolder(folder);
+    }
+}
+
 void SocketApi::copyUrlToClipboard(const QString &link)
 {
     QApplication::clipboard()->setText(link);
@@ -979,12 +1014,23 @@ void SocketApi::command_GET_MENU_ITEMS(const QString &argument, OCC::SocketListe
     if (syncFolder) {
         auto virtualFileSuffix = QStringLiteral(APPLICATION_DOTVIRTUALFILE_SUFFIX);
         bool hasVirtualFile = false;
+        bool hasNormalFiles = false;
+        bool hasDir = false;
         for (const auto &file : files) {
-            if (file.endsWith(virtualFileSuffix) || (syncFolder->useVirtualFiles() && QFileInfo(file).isDir()))
+            if (QFileInfo(file).isDir()) {
+                hasDir = true;
+            } else if (file.endsWith(virtualFileSuffix)) {
                 hasVirtualFile = true;
+            } else if (!hasNormalFiles) {
+                bool isOnTheServer = FileData::get(file).journalRecord().isValid();
+                hasNormalFiles = isOnTheServer;
+            }
         }
-        if (hasVirtualFile)
+        if (hasVirtualFile || (hasDir && syncFolder->useVirtualFiles()))
             listener->sendMessage(QLatin1String("MENU_ITEM:DOWNLOAD_VIRTUAL_FILE::") + tr("Download file(s)", "", files.size()));
+
+        if ((hasNormalFiles || hasDir) && syncFolder->useVirtualFiles())
+            listener->sendMessage(QLatin1String("MENU_ITEM:REPLACE_VIRTUAL_FILE::") + tr("Replace file(s) by virtual file", "", files.size()));
     }
 
     listener->sendMessage(QString("GET_MENU_ITEMS:END"));
index 286530a7d13faee6bcd3237cf5820d333b25a8a4..e16bee72a348dc08b1420ab0d33ceaa324a8a4c5 100644 (file)
@@ -110,6 +110,7 @@ private:
     Q_INVOKABLE void command_EMAIL_PRIVATE_LINK(const QString &localFile, SocketListener *listener);
     Q_INVOKABLE void command_OPEN_PRIVATE_LINK(const QString &localFile, SocketListener *listener);
     Q_INVOKABLE void command_DOWNLOAD_VIRTUAL_FILE(const QString &filesArg, SocketListener *listener);
+    Q_INVOKABLE void command_REPLACE_VIRTUAL_FILE(const QString &filesArg, SocketListener *listener);
     Q_INVOKABLE void command_RESOLVE_CONFLICT(const QString &localFile, SocketListener *listener);
     Q_INVOKABLE void command_DELETE_ITEM(const QString &localFile, SocketListener *listener);
     Q_INVOKABLE void command_MOVE_ITEM(const QString &localFile, SocketListener *listener);