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

Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
This commit is contained in:
Claudio Cambra 2022-10-28 19:40:06 +02:00 committed by Claudio Cambra
parent 4b6fdcc550
commit 9f7a699ad9
7 changed files with 169 additions and 45 deletions

View File

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

View File

@ -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;

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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

View File

@ -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();
}
}

View File

@ -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;
};
}