${CMAKE_CURRENT_LIST_DIR}/utility.cpp
${CMAKE_CURRENT_LIST_DIR}/remotepermissions.cpp
${CMAKE_CURRENT_LIST_DIR}/vfs.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/plugin.cpp
)
--- /dev/null
+/*
+ * Copyright (C) by Dominik Schmidt <dschmidt@owncloud.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "plugin.h"
+
+#include "config.h"
+
+#include <QPluginLoader>
+#include <QDir>
+#include <QLoggingCategory>
+
+Q_LOGGING_CATEGORY(lcPluginLoader, "pluginLoader", QtInfoMsg)
+
+namespace OCC {
+
+PluginFactory::~PluginFactory() = default;
+
+QString PluginLoader::pluginName(const QString &type, const QString &name)
+{
+ return QString(QLatin1String("%1sync_%2_%3"))
+ .arg(APPLICATION_EXECUTABLE)
+ .arg(type)
+ .arg(name);
+}
+
+bool PluginLoader::isAvailable(const QString &type, const QString &name)
+{
+ QPluginLoader loader(pluginName(type, name));
+ return loader.load();
+}
+
+QObject *PluginLoader::load(const QString &type, const QString &name)
+{
+ QString fileName = pluginName(type, name);
+ QPluginLoader pluginLoader(fileName);
+ if (pluginLoader.load()) {
+ qCInfo(lcPluginLoader) << "Loaded plugin" << fileName;
+ } else {
+ qCWarning(lcPluginLoader) << "Could not load plugin"
+ << fileName <<":"
+ << pluginLoader.errorString()
+ << "from" << QDir::currentPath();
+ }
+
+ return pluginLoader.instance();
+}
+
+QObject *PluginLoader::create(const QString &type, const QString &name, QObject *parent)
+{
+ auto factory = qobject_cast<PluginFactory *>(load(type, name));
+ if (!factory) {
+ return nullptr;
+ } else {
+ return factory->create(parent);
+ }
+}
+
+}
--- /dev/null
+/*
+ * Copyright (C) by Dominik Schmidt <dschmidt@owncloud.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include "ocsynclib.h"
+#include <QObject>
+#include <QPluginLoader>
+
+namespace OCC {
+
+class OCSYNC_EXPORT PluginFactory
+{
+public:
+ ~PluginFactory();
+ virtual QObject* create(QObject* parent) = 0;
+};
+
+template<class PLUGIN_CLASS>
+class DefaultPluginFactory : public PluginFactory
+{
+public:
+ QObject* create(QObject *parent) override
+ {
+ return new PLUGIN_CLASS(parent);
+ }
+};
+
+class OCSYNC_EXPORT PluginLoader
+{
+public:
+ static QString pluginName(const QString &type, const QString &name);
+
+ bool isAvailable(const QString &type, const QString &name);
+ QObject *load(const QString &type, const QString &name);
+ QObject *create(const QString &type, const QString &name, QObject *parent = nullptr);
+};
+
+}
+
+Q_DECLARE_INTERFACE(OCC::PluginFactory, "org.owncloud.PluginFactory")
*/
#include "vfs.h"
+#include "plugin.h"
using namespace OCC;
}
return false;
}
+
+static QString modeToPluginName(Vfs::Mode mode)
+{
+ if (mode == Vfs::WithSuffix)
+ return "suffix";
+ if (mode == Vfs::WindowsCfApi)
+ return "win";
+ return QString();
+}
+
+bool OCC::isVfsPluginAvailable(Vfs::Mode mode)
+{
+ auto name = modeToPluginName(mode);
+ if (name.isEmpty())
+ return false;
+ return PluginLoader().load("vfs", name);
+}
+
+Vfs::Mode OCC::bestAvailableVfsMode()
+{
+ if (isVfsPluginAvailable(Vfs::WindowsCfApi)) {
+ return Vfs::WindowsCfApi;
+ } else if (isVfsPluginAvailable(Vfs::WithSuffix)) {
+ return Vfs::WithSuffix;
+ }
+ return Vfs::Off;
+}
+
+Vfs *OCC::createVfsFromPlugin(Vfs::Mode mode, QObject *parent)
+{
+ auto name = modeToPluginName(mode);
+ if (name.isEmpty())
+ return nullptr;
+ return qobject_cast<Vfs *>(PluginLoader().create("vfs", name, parent));
+}
void doneHydrating();
};
+bool isVfsPluginAvailable(Vfs::Mode mode) OCSYNC_EXPORT;
+Vfs::Mode bestAvailableVfsMode() OCSYNC_EXPORT;
+Vfs *createVfsFromPlugin(Vfs::Mode mode, QObject *parent) OCSYNC_EXPORT;
+
} // namespace OCC
folderWizard->property("targetPath").toString());
if (folderWizard->property("useVirtualFiles").toBool()) {
- // ### Determine which vfs is available?
- definition.virtualFilesMode = Vfs::WindowsCfApi;
+ definition.virtualFilesMode = bestAvailableVfsMode();
}
{
#include "owncloudsetupwizard.h"
#include "version.h"
#include "csync_exclude.h"
+#include "common/vfs.h"
#include "config.h"
if (!AbstractNetworkJob::httpTimeout)
AbstractNetworkJob::httpTimeout = cfg.timeout();
+ // Check vfs plugins
+ if (Theme::instance()->showVirtualFilesOption() && bestAvailableVfsMode() == Vfs::Off) {
+ qCWarning(lcApplication) << "Theme wants to show vfs mode, but no vfs plugins are available";
+ }
+ if (isVfsPluginAvailable(Vfs::WindowsCfApi))
+ qCInfo(lcApplication) << "VFS windows plugin is available";
+ if (isVfsPluginAvailable(Vfs::WithSuffix))
+ qCInfo(lcApplication) << "VFS suffix plugin is available";
+
_folderManager.reset(new FolderMan);
connect(this, &SharedTools::QtSingleApplication::messageReceived, this, &Application::slotParseMessage);
#include "localdiscoverytracker.h"
#include "csync_exclude.h"
#include "common/vfs.h"
-#include "plugin.h"
#include "creds/abstractcredentials.h"
#include <QTimer>
Q_LOGGING_CATEGORY(lcFolder, "nextcloud.gui.folder", QtInfoMsg)
Folder::Folder(const FolderDefinition &definition,
- AccountState *accountState,
+ AccountState *accountState, Vfs *vfs,
QObject *parent)
: QObject(parent)
, _accountState(accountState)
, _consecutiveFollowUpSyncs(0)
, _journal(_definition.absoluteJournalPath())
, _fileLog(new SyncRunFileLog)
+ , _vfs(vfs)
{
_timeSinceLastSyncStart.start();
_timeSinceLastSyncDone.start();
connect(_engine.data(), &SyncEngine::itemCompleted,
_localDiscoveryTracker.data(), &LocalDiscoveryTracker::slotItemCompleted);
- // TODO cfapi: Move to function. Is this platform-universal?
- PluginLoader pluginLoader;
- if (_definition.virtualFilesMode == Vfs::WindowsCfApi) {
- _vfs = pluginLoader.create<Vfs>("vfs", "win", this);
- }
- if (_definition.virtualFilesMode == Vfs::WithSuffix) {
- _vfs = pluginLoader.create<Vfs>("vfs", "suffix", this);
-
- // Attempt to switch to winvfs mode?
- if (_vfs && _definition.upgradeVfsMode) {
- if (auto winvfs = pluginLoader.create<Vfs>("vfs", "win", this)) {
- // Set "suffix" vfs options and wipe the existing suffix files
- SyncEngine::wipeVirtualFiles(path(), _journal, _vfs);
-
- // Then switch to winvfs mode
- _vfs = winvfs;
- _definition.virtualFilesMode = Vfs::WindowsCfApi;
- saveToSettings();
- }
+ // Potentially upgrade suffix vfs to windows vfs
+ if (_definition.virtualFilesMode == Vfs::WithSuffix && _definition.upgradeVfsMode) {
+ if (auto winvfs = createVfsFromPlugin(Vfs::WindowsCfApi, this)) {
+ // Wipe the existing suffix files from fs and journal
+ SyncEngine::wipeVirtualFiles(path(), _journal, _vfs);
+
+ // Then switch to winvfs mode
+ delete _vfs;
+ _vfs = winvfs;
+ _definition.virtualFilesMode = Vfs::WindowsCfApi;
+ saveToSettings();
}
}
+
+ // Initialize the vfs plugin
if (_definition.virtualFilesMode != Vfs::Off) {
- if (!_vfs) {
- // ### error handling; possibly earlier than in the ctor
- qFatal("Could not load any vfs plugin.");
- }
+ ENFORCE(_vfs);
+ ENFORCE(_vfs->mode() == _definition.virtualFilesMode);
+
+ _vfs->setParent(this);
VfsSetupParams vfsParams;
vfsParams.filesystemPath = path();
Q_OBJECT
public:
- Folder(const FolderDefinition &definition, AccountState *accountState, QObject *parent = nullptr);
+ /** Create a new Folder
+ *
+ * The vfs instance will be parented to this.
+ */
+ Folder(const FolderDefinition &definition, AccountState *accountState, Vfs *vfs, QObject *parent = nullptr);
~Folder();
qCInfo(lcFolderMan) << "Successfully migrated syncjournal database.";
}
- Folder *f = addFolderInternal(folderDefinition, account.data());
+ Vfs *vfs = createVfsFromPlugin(folderDefinition.virtualFilesMode, nullptr);
+ if (!vfs && folderDefinition.virtualFilesMode != Vfs::Off) {
+ qCWarning(lcFolderMan) << "Could not load plugin for mode" << folderDefinition.virtualFilesMode;
+ }
+
+ Folder *f = addFolderInternal(folderDefinition, account.data(), vfs);
f->saveToSettings();
continue;
SyncJournalDb::maybeMigrateDb(folderDefinition.localPath, folderDefinition.absoluteJournalPath());
}
- Folder *f = addFolderInternal(std::move(folderDefinition), account.data());
+ Vfs *vfs = createVfsFromPlugin(folderDefinition.virtualFilesMode, nullptr);
+ if (!vfs && folderDefinition.virtualFilesMode != Vfs::Off) {
+ // TODO: Must do better error handling
+ qFatal("Could not load plugin");
+ }
+
+ Folder *f = addFolderInternal(std::move(folderDefinition), account.data(), vfs);
if (f) {
// Migration: Mark folders that shall be saved in a backwards-compatible way
if (backwardsCompatible)
folderDefinition.paused = paused;
folderDefinition.ignoreHiddenFiles = ignoreHiddenFiles();
- folder = addFolderInternal(folderDefinition, accountState);
+ Vfs *vfs = nullptr;
+ folder = addFolderInternal(folderDefinition, accountState, vfs);
if (folder) {
QStringList blackList = settings.value(QLatin1String("blackList")).toStringList();
if (!blackList.empty()) {
return nullptr;
}
- auto folder = addFolderInternal(definition, accountState);
+ Vfs *vfs = createVfsFromPlugin(folderDefinition.virtualFilesMode, nullptr);
+ if (!vfs && folderDefinition.virtualFilesMode != Vfs::Off) {
+ qCWarning(lcFolderMan) << "Could not load plugin for mode" << folderDefinition.virtualFilesMode;
+ return 0;
+ }
+
+ auto folder = addFolderInternal(definition, accountState, vfs);
// Migration: The first account that's configured for a local folder shall
// be saved in a backwards-compatible way.
folder->setSaveBackwardsCompatible(oneAccountOnly);
if (folder) {
+ folder->setSaveBackwardsCompatible(oneAccountOnly);
folder->saveToSettings();
emit folderSyncStateChange(folder);
emit folderListChanged(_folderMap);
return folder;
}
-Folder *FolderMan::addFolderInternal(FolderDefinition folderDefinition,
- AccountState *accountState)
+Folder *FolderMan::addFolderInternal(
+ FolderDefinition folderDefinition,
+ AccountState *accountState,
+ Vfs *vfs)
{
auto alias = folderDefinition.alias;
int count = 0;
folderDefinition.alias = alias + QString::number(++count);
}
- auto folder = new Folder(folderDefinition, accountState, this);
+ auto folder = new Folder(folderDefinition, accountState, vfs, this);
if (_navigationPaneHelper.showInExplorerNavigationPane() && folderDefinition.navigationPaneClsid.isNull()) {
folder->setNavigationPaneClsid(QUuid::createUuid());
* does not set an account on the new folder.
*/
Folder *addFolderInternal(FolderDefinition folderDefinition,
- AccountState *accountState);
+ AccountState *accountState, Vfs *vfs);
/* unloads a folder object, does not delete it */
void unloadFolder(Folder *);
_selectiveSync = new SelectiveSyncWidget(account, this);
layout->addWidget(_selectiveSync);
- if (Theme::instance()->showVirtualFilesOption()) {
+ if (Theme::instance()->showVirtualFilesOption() && bestAvailableVfsMode() != Vfs::Off) {
_virtualFilesCheckBox = new QCheckBox(tr("Use virtual files instead of downloading content immediately (experimental)"));
connect(_virtualFilesCheckBox, &QCheckBox::clicked, this, &FolderWizardSelectiveSync::virtualFilesCheckboxClicked);
connect(_virtualFilesCheckBox, &QCheckBox::stateChanged, this, [this](int state) {
folderDefinition.targetPath = FolderDefinition::prepareTargetPath(_remoteFolder);
folderDefinition.ignoreHiddenFiles = folderMan->ignoreHiddenFiles();
if (_ocWizard->useVirtualFileSync()) {
- // ### determine best vfs mode!
- folderDefinition.virtualFilesMode = Vfs::WindowsCfApi;
+ folderDefinition.virtualFilesMode = bestAvailableVfsMode();
}
if (folderMan->navigationPaneHelper().showInExplorerNavigationPane())
folderDefinition.navigationPaneClsid = QUuid::createUuid();
{
WizardCommon::initErrorLabel(_ui.errorLabel);
- if (!Theme::instance()->showVirtualFilesOption()) {
+ if (!Theme::instance()->showVirtualFilesOption() || bestAvailableVfsMode() == Vfs::Off) {
// If the layout were wrapped in a widget, the auto-grouping of the
// radio buttons no longer works and there are surprising margins.
// Just manually hide the button and remove the layout.
#include "wizard/webviewpage.h"
#include "wizard/flow2authcredspage.h"
+#include "common/vfs.h"
+
#include "QProgressIndicator.h"
#include <QtCore>
void OwncloudWizard::askExperimentalVirtualFilesFeature(const std::function<void(bool enable)> &callback)
{
- auto msgBox = new QMessageBox(
- QMessageBox::Warning,
- tr("Enable experimental feature?"),
- tr("When the \"virtual files\" mode is enabled no files will be downloaded initially. "
- "Instead, a tiny \"%1\" file will be created for each file that exists on the server. "
- "The contents can be downloaded by running these files or by using their context menu."
- "\n\n"
- "This is a new, experimental mode. If you decide to use it, please report any "
- "issues that come up.")
- .arg(APPLICATION_DOTVIRTUALFILE_SUFFIX));
+ auto bestVfsMode = bestAvailableVfsMode();
+ QMessageBox *msgBox = nullptr;
+ if (bestVfsMode == Vfs::WindowsCfApi) {
+ msgBox = new QMessageBox(
+ QMessageBox::Warning,
+ tr("Enable experimental feature?"),
+ tr("When the \"virtual files\" mode is enabled no files will be downloaded initially. "
+ "Instead a placeholder file will be created for each file that exists on the server. "
+ "When a file is opened its contents will be downloaded automatically. "
+ "Alternatively files can be downloaded manually by using their context menu."
+ "\n\n"
+ "This is a new, experimental mode. If you decide to use it, please report any "
+ "issues that come up."));
+ } else {
+ ASSERT(bestVfsMode == Vfs::WithSuffix);
+ msgBox = new QMessageBox(
+ QMessageBox::Warning,
+ tr("Enable experimental feature?"),
+ tr("When the \"virtual files\" mode is enabled no files will be downloaded initially. "
+ "Instead, a tiny \"%1\" file will be created for each file that exists on the server. "
+ "The contents can be downloaded by running these files or by using their context menu."
+ "\n\n"
+ "This is a new, experimental mode. If you decide to use it, please report any "
+ "issues that come up.")
+ .arg(APPLICATION_DOTVIRTUALFILE_SUFFIX));
+ }
msgBox->addButton(tr("Enable experimental mode"), QMessageBox::AcceptRole);
msgBox->addButton(tr("Stay safe"), QMessageBox::RejectRole);
connect(msgBox, &QMessageBox::finished, msgBox, [callback, msgBox](int result) {
networkjobs.cpp
owncloudpropagator.cpp
nextcloudtheme.cpp
- plugin.cpp
progressdispatcher.cpp
propagatorjobs.cpp
propagatedownload.cpp
#include <qmutex.h>
#include "common/utility.h"
-#include "logger.h"
#include "owncloudlib.h"
namespace OCC {
+++ /dev/null
-/*
- * Copyright (C) by Dominik Schmidt <dschmidt@owncloud.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "plugin.h"
-
-#include "config.h"
-#include "logger.h"
-
-#include <QPluginLoader>
-#include <QDir>
-
-Q_LOGGING_CATEGORY(lcPluginLoader, "pluginLoader", QtInfoMsg)
-
-namespace OCC {
-
-PluginFactory::~PluginFactory() = default;
-
-QObject *PluginLoader::createInternal(const QString& type, const QString &name, QObject* parent)
-{
- auto factory = load<PluginFactory>(type, name);
- if (!factory) {
- return nullptr;
- } else {
- return factory->create(parent);
- }
-}
-
-QString PluginLoader::pluginName(const QString &type, const QString &name)
-{
- return QString(QLatin1String("%1sync_%2_%3"))
- .arg(APPLICATION_EXECUTABLE)
- .arg(type)
- .arg(name);
-}
-
-QObject *PluginLoader::loadPluginInternal(const QString& type, const QString &name)
-{
- QString fileName = pluginName(type, name);
- QPluginLoader pluginLoader(fileName);
- auto plugin = pluginLoader.load();
- if(plugin) {
- qCInfo(lcPluginLoader) << "Loaded plugin" << fileName;
- } else {
- qCWarning(lcPluginLoader) << "Could not load plugin"
- << fileName <<":"
- << pluginLoader.errorString()
- << "from" << QDir::currentPath();
- }
-
- return pluginLoader.instance();
-}
-
-}
+++ /dev/null
-/*
- * Copyright (C) by Dominik Schmidt <dschmidt@owncloud.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#pragma once
-
-#include "owncloudlib.h"
-#include <QObject>
-#include <QPluginLoader>
-
-namespace OCC {
-
-class OWNCLOUDSYNC_EXPORT PluginFactory
-{
-public:
- ~PluginFactory();
- virtual QObject* create(QObject* parent) = 0;
-};
-
-template<class PLUGIN_CLASS>
-class DefaultPluginFactory : public PluginFactory
-{
-public:
- QObject* create(QObject* parent) override
- {
- return new PLUGIN_CLASS(parent);
- }
-};
-
-class OWNCLOUDSYNC_EXPORT PluginLoader
-{
-public:
- static QString pluginName(const QString &type, const QString &name);
-
- template<class PLUGIN_CLASS, typename ... Args>
- PLUGIN_CLASS *create(Args&& ... args)
- {
- return qobject_cast<PLUGIN_CLASS*>(createInternal(std::forward<Args>(args)...));
- }
-
-private:
- template<class FACTORY_CLASS, typename ... Args>
- FACTORY_CLASS *load(Args&& ... args)
- {
- return qobject_cast<FACTORY_CLASS*>(loadPluginInternal(std::forward<Args>(args)...));
- }
-
- QObject *loadPluginInternal(const QString& type, const QString &name);
- QObject *createInternal(const QString& type, const QString &name, QObject* parent = nullptr);
-};
-
-}
-
-Q_DECLARE_INTERFACE(OCC::PluginFactory, "org.owncloud.PluginFactory")
#include <QScopedPointer>
#include "common/vfs.h"
-#include "plugin.h"
+#include "common/plugin.h"
namespace OCC {
#include <QtTest>
#include "syncenginetestutils.h"
#include "common/vfs.h"
-#include "plugin.h"
#include <syncengine.h>
using namespace OCC;
SyncOptions vfsSyncOptions()
{
SyncOptions options;
- options._vfs = PluginLoader().create<Vfs>("vfs", "suffix");
+ options._vfs = createVfsFromPlugin(Vfs::WithSuffix, nullptr);
return options;
}