Browse Source

Refactor edit locally handler management away from application and into own class

Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
Claudio Cambra 3 years ago
parent
commit
9f7a699ad9

+ 2 - 0
src/gui/CMakeLists.txt

@@ -83,6 +83,8 @@ set(client_SRCS
     connectionvalidator.cpp
     editlocallyhandler.h
     editlocallyhandler.cpp
+    editlocallymanager.h
+    editlocallymanager.cpp
     folder.h
     folder.cpp
     foldercreationdialog.h

+ 3 - 36
src/gui/application.cpp

@@ -22,7 +22,7 @@
 #include "config.h"
 #include "account.h"
 #include "accountstate.h"
-#include "editlocallyhandler.h"
+#include "editlocallymanager.h"
 #include "connectionvalidator.h"
 #include "folder.h"
 #include "folderman.h"
@@ -750,43 +750,10 @@ void Application::handleEditLocallyFromOptions()
         return;
     }
 
-    handleEditLocally(_editFileLocallyUrl);
+    EditLocallyManager::instance()->editLocally(_editFileLocallyUrl);
     _editFileLocallyUrl.clear();
 }
 
-void Application::handleEditLocally(const QUrl &url) const
-{
-    auto pathSplit = url.path().split('/', Qt::SkipEmptyParts);
-
-    if (pathSplit.size() < 2) {
-        qCWarning(lcApplication) << "Invalid URL for file local editing: " + pathSplit.join('/');
-        return;
-    }
-
-    // for a sample URL "nc://open/admin@nextcloud.lan:8080/Photos/lovely.jpg", QUrl::path would return "admin@nextcloud.lan:8080/Photos/lovely.jpg"
-    const auto userId = pathSplit.takeFirst();
-    const auto fileRemotePath = pathSplit.join('/');
-    const auto urlQuery = QUrlQuery{url};
-
-    auto token = QString{};
-    if (urlQuery.hasQueryItem(QStringLiteral("token"))) {
-        token = urlQuery.queryItemValue(QStringLiteral("token"));
-    } else {
-        qCWarning(lcApplication) << "Invalid URL for file local editing: missing token";
-    }
-
-    // We need to make sure the handler sticks around until it is finished
-    const auto editLocallyHandler = new EditLocallyHandler(userId, fileRemotePath, token);
-    const auto editLocallyHandlerDeleter = [editLocallyHandler]{ delete editLocallyHandler; };
-    connect(editLocallyHandler, &EditLocallyHandler::error, this, editLocallyHandlerDeleter);
-    connect(editLocallyHandler, &EditLocallyHandler::fileOpened, this, editLocallyHandlerDeleter);
-
-    connect(editLocallyHandler, &EditLocallyHandler::setupFinished,
-            editLocallyHandler, [editLocallyHandler]{ editLocallyHandler->startEditLocally(); });
-    editLocallyHandler->startSetup();
-
-}
-
 QString substLang(const QString &lang)
 {
     // Map the more appropriate script codes
@@ -927,7 +894,7 @@ bool Application::event(QEvent *event)
             // On macOS, Qt does not handle receiving a custom URI as it does on other systems (as an application argument).
             // Instead, it sends out a QFileOpenEvent. We therefore need custom handling for our URI handling on macOS.
             qCInfo(lcApplication) << "macOS: Opening local file for editing: " << openEvent->url();
-            handleEditLocally(openEvent->url());
+            EditLocallyManager::instance()->editLocally(openEvent->url());
         } else {
             const auto errorParsingLocalFileEditingUrl = QStringLiteral("The supplied url for local file editing '%1' is invalid!").arg(openEvent->url().toString());
             qCInfo(lcApplication) << errorParsingLocalFileEditingUrl;

+ 0 - 2
src/gui/application.h

@@ -87,8 +87,6 @@ public slots:
     /// Attempt to show() the tray icon again. Used if no systray was available initially.
     void tryTrayAgain();
 
-    void handleEditLocally(const QUrl &url) const;
-
 protected:
     void parseOptions(const QStringList &);
     void setupTranslations();

+ 8 - 5
src/gui/editlocallyhandler.cpp

@@ -19,6 +19,7 @@
 #include <QtConcurrent>
 
 #include "accountmanager.h"
+#include "editlocallymanager.h"
 #include "folder.h"
 #include "folderman.h"
 #include "syncengine.h"
@@ -28,8 +29,6 @@ namespace OCC {
 
 Q_LOGGING_CATEGORY(lcEditLocallyHandler, "nextcloud.gui.editlocallyhandler", QtInfoMsg)
 
-static QHash<QString, QMetaObject::Connection> editLocallySyncFinishedConnections;
-
 EditLocallyHandler::EditLocallyHandler(const QString &userId,
                                        const QString &relPath,
                                        const QString &token,
@@ -277,7 +276,9 @@ void EditLocallyHandler::startEditLocally()
     _folderForFile->startSync();
     const auto syncFinishedConnection = connect(_folderForFile, &Folder::syncFinished,
                                                 this, &EditLocallyHandler::folderSyncFinished);
-    editLocallySyncFinishedConnections.insert(_localFilePath, syncFinishedConnection);
+
+    EditLocallyManager::instance()->folderSyncFinishedConnections.insert(_localFilePath,
+                                                                         syncFinishedConnection);
 }
 
 void EditLocallyHandler::folderSyncFinished(const OCC::SyncResult &result)
@@ -293,9 +294,11 @@ void EditLocallyHandler::disconnectSyncFinished() const
         return;
     }
 
-    if (const auto existingConnection = editLocallySyncFinishedConnections.value(_localFilePath)) {
+    const auto manager = EditLocallyManager::instance();
+
+    if (const auto existingConnection = manager->folderSyncFinishedConnections.value(_localFilePath)) {
         disconnect(existingConnection);
-        editLocallySyncFinishedConnections.remove(_localFilePath);
+        manager->folderSyncFinishedConnections.remove(_localFilePath);
     }
 }
 

+ 7 - 2
src/gui/editlocallyhandler.h

@@ -16,11 +16,16 @@
 
 #include <QObject>
 
-#include "accountmanager.h"
-#include "folder.h"
+#include "accountstate.h"
 
 namespace OCC {
 
+class EditLocallyHandler;
+using EditLocallyHandlerPtr = QSharedPointer<EditLocallyHandler>;
+
+class Folder;
+class SyncResult;
+
 class EditLocallyHandler : public QObject
 {
     Q_OBJECT

+ 93 - 0
src/gui/editlocallymanager.cpp

@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) by Claudio Cambra <claudio.cambra@nextcloud.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "editlocallymanager.h"
+
+#include <QUrl>
+#include <QLoggingCategory>
+
+#include "editlocallyhandler.h"
+
+namespace OCC {
+
+Q_LOGGING_CATEGORY(lcEditLocallyManager, "nextcloud.gui.editlocallymanager", QtInfoMsg)
+
+EditLocallyManager *EditLocallyManager::_instance = nullptr;
+
+EditLocallyManager::EditLocallyManager(QObject *parent)
+    : QObject{parent}
+{
+}
+
+EditLocallyManager *EditLocallyManager::instance()
+{
+    if (!_instance) {
+        _instance = new EditLocallyManager();
+    }
+    return _instance;
+}
+
+void EditLocallyManager::editLocally(const QUrl &url)
+{
+    const auto inputs = parseEditLocallyUrl(url);
+    createHandler(inputs.userId, inputs.relPath, inputs.token);
+}
+
+EditLocallyManager::EditLocallyInputData EditLocallyManager::parseEditLocallyUrl(const QUrl &url)
+{
+    const auto separator = QChar::fromLatin1('/');
+    auto pathSplit = url.path().split(separator, Qt::SkipEmptyParts);
+
+    if (pathSplit.size() < 2) {
+        qCWarning(lcEditLocallyManager) << "Invalid URL for file local editing: " + pathSplit.join(separator);
+        return {};
+    }
+
+    // for a sample URL "nc://open/admin@nextcloud.lan:8080/Photos/lovely.jpg", QUrl::path would return "admin@nextcloud.lan:8080/Photos/lovely.jpg"
+    const auto userId = pathSplit.takeFirst();
+    const auto fileRemotePath = pathSplit.join(separator);
+    const auto urlQuery = QUrlQuery{url};
+
+    auto token = QString{};
+    if (urlQuery.hasQueryItem(QStringLiteral("token"))) {
+        token = urlQuery.queryItemValue(QStringLiteral("token"));
+    } else {
+        qCWarning(lcEditLocallyManager) << "Invalid URL for file local editing: missing token";
+    }
+
+    return {userId, fileRemotePath, token};
+}
+
+void EditLocallyManager::createHandler(const QString &userId,
+                                       const QString &relPath,
+                                       const QString &token)
+{
+    const EditLocallyHandlerPtr handler(new EditLocallyHandler(userId, relPath, token));
+    // We need to make sure the handler sticks around until it is finished
+    _handlers.insert(token, handler);
+
+    const auto removeHandler = [this, token] { _handlers.remove(token); };
+    const auto setupHandler = [handler] { handler->startEditLocally(); };
+
+    connect(handler.data(), &EditLocallyHandler::error,
+            this, removeHandler);
+    connect(handler.data(), &EditLocallyHandler::fileOpened,
+            this, removeHandler);
+    connect(handler.data(), &EditLocallyHandler::setupFinished,
+            handler.data(), setupHandler);
+
+    handler->startSetup();
+}
+
+}

+ 56 - 0
src/gui/editlocallymanager.h

@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) by Claudio Cambra <claudio.cambra@nextcloud.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#pragma once
+
+#include <QObject>
+#include <QHash>
+
+#include "editlocallyhandler.h"
+
+namespace OCC {
+
+class EditLocallyManager : public QObject
+{
+    Q_OBJECT
+
+public:
+    [[nodiscard]] static EditLocallyManager *instance();
+
+    QHash<QString, QMetaObject::Connection> folderSyncFinishedConnections;
+
+public slots:
+    void editLocally(const QUrl &url);
+
+private slots:
+    void createHandler(const QString &userId,
+                       const QString &relPath,
+                       const QString &token);
+
+private:
+    explicit EditLocallyManager(QObject *parent = nullptr);
+    static EditLocallyManager *_instance;
+
+    struct EditLocallyInputData {
+        QString userId;
+        QString relPath;
+        QString token;
+    };
+
+    [[nodiscard]] static EditLocallyInputData parseEditLocallyUrl(const QUrl &url);
+
+    QHash<QString, EditLocallyHandlerPtr> _handlers;
+};
+
+}