Commit 4006a3e4 authored by Nicolas Fella's avatar Nicolas Fella
Browse files

Drop plugin system

The plugin infrastructure is only used for storage backends, for which only one implementation exists in all of KDE.

By removing the plugin infrastructure and making the mk4-based storage plugin the single storage implementation the code can be simplified by a lot
parent 63f2986f
Pipeline #174432 passed with stage
in 3 minutes and 18 seconds
......@@ -114,7 +114,6 @@ if (USE_UNITY_CMAKE_SUPPORT)
endif()
add_subdirectory(export)
add_subdirectory(interfaces)
add_subdirectory(plugins)
add_subdirectory(configuration)
add_subdirectory(src)
add_subdirectory(kontactplugin)
......
......@@ -42,12 +42,10 @@ KCMAkregatorAdvancedConfig::KCMAkregatorAdvancedConfig(QWidget *parent, const QV
void KCMAkregatorAdvancedConfig::load()
{
KCModule::load();
m_widget->selectFactory(Settings::archiveBackend());
}
void KCMAkregatorAdvancedConfig::save()
{
Settings::setArchiveBackend(m_widget->selectedFactory());
KCModule::save();
}
......
......@@ -8,8 +8,6 @@
#include "settings_advanced.h"
#include "akregatorconfig.h"
#include "storagefactory.h"
#include "storagefactoryregistry.h"
#include <KLocalizedString>
......@@ -25,55 +23,7 @@ SettingsAdvanced::SettingsAdvanced(QWidget *parent)
{
setupUi(this);
const QStringList backends = Backend::StorageFactoryRegistry::self()->list();
for (const QString &i : backends) {
Backend::StorageFactory *const factory = Backend::StorageFactoryRegistry::self()->getFactory(i);
if (!factory) {
continue;
}
m_factories.insert(factory->key(), factory);
cbBackend->addItem(factory->name(), factory->key());
}
connect(pbBackendConfigure, &QPushButton::clicked, this, &SettingsAdvanced::slotConfigureStorage);
connect(cbBackend, qOverload<int>(&QComboBox::activated), this, &SettingsAdvanced::slotFactorySelected);
connect(kcfg_UseMarkReadDelay, &QCheckBox::toggled, kcfg_MarkReadDelay, &KPluralHandlingSpinBox::setEnabled);
kcfg_MarkReadDelay->setSuffix(ki18ncp("Mark selected article read after", " second", " seconds"));
}
QString SettingsAdvanced::selectedFactory() const
{
return cbBackend->itemData(cbBackend->currentIndex()).toString();
}
void SettingsAdvanced::selectFactory(const QString &key)
{
const int idx = cbBackend->findData(key);
if (idx < 0) {
return;
}
cbBackend->setCurrentIndex(idx);
const Backend::StorageFactory *const factory = m_factories.value(key);
Q_ASSERT(factory);
pbBackendConfigure->setEnabled(factory->isConfigurable());
}
void SettingsAdvanced::slotConfigureStorage()
{
const QString key = cbBackend->itemData(cbBackend->currentIndex()).toString();
if (!key.isEmpty()) {
Backend::StorageFactory *const factory = m_factories.value(key);
Q_ASSERT(factory);
factory->configure();
}
}
void SettingsAdvanced::slotFactorySelected(int pos)
{
const QString key = cbBackend->itemData(pos).toString();
const Backend::StorageFactory *const factory = m_factories.value(key);
Q_ASSERT(factory);
pbBackendConfigure->setEnabled(factory->isConfigurable());
}
......@@ -28,18 +28,5 @@ class SettingsAdvanced : public QWidget, public Ui::SettingsAdvancedBase
public:
explicit SettingsAdvanced(QWidget *parent = nullptr);
/** returns the key of the currently selected factory */
QString selectedFactory() const;
void selectFactory(const QString &key);
public Q_SLOTS:
void slotConfigureStorage();
void slotFactorySelected(int);
private:
QHash<QString, Backend::StorageFactory *> m_factories;
};
} // namespace Akregator
......@@ -11,7 +11,7 @@
<height>207</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,0,1">
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1">
<property name="leftMargin">
<number>0</number>
</property>
......@@ -24,49 +24,6 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Archive</string>
</property>
<layout class="QGridLayout">
<item row="0" column="0">
<layout class="QHBoxLayout">
<item>
<widget class="QLabel" name="textLabel1">
<property name="text">
<string>Archive backend:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cbBackend"/>
</item>
<item>
<widget class="QPushButton" name="pbBackendConfigure">
<property name="text">
<string>&amp;Configure...</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
......
......@@ -9,7 +9,7 @@ add_executable(akregatorstorageexporter)
target_sources(akregatorstorageexporter PRIVATE akregatorstorageexporter.cpp)
target_link_libraries(akregatorstorageexporter
KF5::Syndication
akregatorinterfaces
akregatorprivate
KF5::Service
KF5::I18n
)
......
......@@ -6,11 +6,8 @@
* SPDX-License-Identifier: LGPL-2.0-or-later
*
*/
#include "feedstorage.h"
#include "plugin.h"
#include "storage.h"
#include "storagefactory.h"
#include "storagefactoryregistry.h"
#include "storage/feedstorage.h"
#include "storage/storage.h"
#include <KLocalizedString>
#include <Syndication/Atom/Atom>
#include <Syndication/Constants>
......@@ -290,24 +287,6 @@ static void serialize(Storage *storage, const QString &url, QIODevice *device)
serialize(storage->archiveFor(url), url, device);
}
static KService::List queryStoragePlugins()
{
return KServiceTypeTrader::self()->query(
QStringLiteral("Akregator/Plugin"),
QStringLiteral("[X-KDE-akregator-framework-version] == %1 and [X-KDE-akregator-plugintype] == 'storage' and [X-KDE-akregator-rank] > 0")
.arg(QString::number(AKREGATOR_PLUGIN_INTERFACE_VERSION)));
}
static Plugin *createFromService(const KService::Ptr &service)
{
KPluginFactory *factory = KPluginFactory::loadFactory(KPluginMetaData(service->library())).plugin;
if (!factory) {
qCritical() << QStringLiteral(" Could not create plugin factory for: %1").arg(service->library());
return nullptr;
}
return factory->create<Akregator::Plugin>();
}
static void printUsage()
{
std::cout << "akregatorstorageexporter [--base64] url" << std::endl;
......@@ -317,7 +296,6 @@ static void printUsage()
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
const QString backend = QStringLiteral("metakit");
if (argc < 2) {
printUsage();
......@@ -334,24 +312,7 @@ int main(int argc, char *argv[])
const int pos = base64 ? 2 : 1;
const QString url = QUrl::fromEncoded(base64 ? QByteArray::fromBase64(argv[pos]) : QByteArray(argv[pos])).toString();
const auto plugins = queryStoragePlugins();
for (const KService::Ptr &i : plugins) {
if (Plugin *const plugin = createFromService(i)) {
plugin->initialize();
}
}
const StorageFactory *const storageFactory = StorageFactoryRegistry::self()->getFactory(backend);
if (!storageFactory) {
qCritical() << "Could not create storage factory for " << qPrintable(backend);
return 1;
}
Storage *const storage = storageFactory->createStorage(QStringList());
if (!storage) {
qCritical() << "Could not create storage object for " << qPrintable(backend);
return 1;
}
Storage storage;
QFile out;
if (!out.open(stdout, QIODevice::WriteOnly)) {
......@@ -359,7 +320,7 @@ int main(int argc, char *argv[])
return 1;
}
serialize(storage, url, &out);
serialize(&storage, url, &out);
return app.exec();
}
......@@ -6,8 +6,6 @@ add_library(akregatorinterfaces)
target_sources(akregatorinterfaces PRIVATE
command.cpp
feedlistmanagementinterface.cpp
plugin.cpp
storagefactoryregistry.cpp
)
set(akregatorinterfaces_userfeedback_LIB_SRCS)
......
/*
This file is part of Akregator.
SPDX-FileCopyrightText: 2005 Frank Osterfeld <osterfeld@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
*/
#pragma once
#include <QObject>
class QString;
#include <QStringList>
class QDateTime;
namespace Akregator
{
namespace Backend
{
class Storage;
class FeedStorage : public QObject // krazy:exclude=qobject
{
public:
virtual int unread() const = 0;
virtual void setUnread(int unread) = 0;
virtual int totalCount() const = 0;
virtual QDateTime lastFetch() const = 0;
virtual void setLastFetch(const QDateTime &lastFetch) = 0;
/** returns the guids of all articles in this storage. */
virtual QStringList articles() const = 0;
virtual void article(const QString &guid, uint &hash, QString &title, int &status, QDateTime &pubDate) const = 0;
virtual bool contains(const QString &guid) const = 0;
virtual void addEntry(const QString &guid) = 0;
virtual void deleteArticle(const QString &guid) = 0;
virtual bool guidIsHash(const QString &guid) const = 0;
virtual void setGuidIsHash(const QString &guid, bool isHash) = 0;
virtual bool guidIsPermaLink(const QString &guid) const = 0;
virtual void setGuidIsPermaLink(const QString &guid, bool isPermaLink) = 0;
virtual uint hash(const QString &guid) const = 0;
virtual void setHash(const QString &guid, uint hash) = 0;
virtual void setDeleted(const QString &guid) = 0;
virtual QString link(const QString &guid) const = 0;
virtual void setLink(const QString &guid, const QString &link) = 0;
virtual QDateTime pubDate(const QString &guid) const = 0;
virtual void setPubDate(const QString &guid, const QDateTime &pubdate) = 0;
virtual int status(const QString &guid) const = 0;
virtual void setStatus(const QString &guid, int status) = 0;
virtual QString title(const QString &guid) const = 0;
virtual void setTitle(const QString &guid, const QString &title) = 0;
virtual QString description(const QString &guid) const = 0;
virtual void setDescription(const QString &guid, const QString &description) = 0;
virtual QString content(const QString &guid) const = 0;
virtual void setContent(const QString &guid, const QString &content) = 0;
virtual void setEnclosure(const QString &guid, const QString &url, const QString &type, int length) = 0;
virtual void removeEnclosure(const QString &guid) = 0;
virtual void setAuthorName(const QString & /*guid*/, const QString &name) = 0;
virtual void setAuthorUri(const QString & /*guid*/, const QString &uri) = 0;
virtual void setAuthorEMail(const QString & /*guid*/, const QString &email) = 0;
virtual QString authorName(const QString &guid) const = 0;
virtual QString authorUri(const QString &guid) const = 0;
virtual QString authorEMail(const QString &guid) const = 0;
virtual void enclosure(const QString &guid, bool &hasEnclosure, QString &url, QString &type, int &length) const = 0;
virtual void setCategories(const QString & /*guid*/, const QStringList &categories) = 0;
virtual QStringList categories(const QString &guid) const = 0;
};
} // namespace Backend
} // namespace Akregator
/*
This file is part of Akregator.
SPDX-FileCopyrightText: 2004 Mark Kretschmann <kretschmann@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
*/
#include "plugin.h"
namespace Akregator
{
Plugin::Plugin(QObject *parent, const QVariantList &)
: QObject(parent)
{
}
Plugin::~Plugin() = default;
void Plugin::addPluginProperty(const QString &key, const QString &value)
{
m_properties[key.toLower()] = value;
}
void Plugin::initialize()
{
doInitialize();
}
QString Plugin::pluginProperty(const QString &key) const
{
if (m_properties.find(key.toLower()) == m_properties.end()) {
return QStringLiteral("false");
}
return m_properties[key.toLower()];
}
bool Plugin::hasPluginProperty(const QString &key) const
{
return m_properties.find(key.toLower()) != m_properties.end();
}
void Plugin::insertGuiClients(KXMLGUIClient *)
{
}
void Plugin::removeGuiClients(KXMLGUIClient *)
{
}
}
/*
This file is part of Akregator.
SPDX-FileCopyrightText: 2004 Mark Kretschmann <kretschmann@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
*/
#pragma once
#include "akregatorinterfaces_export.h"
#include <QHash>
#include <QObject>
#include <QString>
#include <QVariant>
class KXMLGUIClient;
#define AKREGATOR_PLUGIN_INTERFACE_VERSION 4
namespace Akregator
{
class AKREGATORINTERFACES_EXPORT Plugin : public QObject
{
Q_OBJECT
public:
explicit Plugin(QObject *parent = nullptr, const QVariantList &opts = QVariantList());
~Plugin() override;
void initialize();
void addPluginProperty(const QString &key, const QString &value);
Q_REQUIRED_RESULT QString pluginProperty(const QString &key) const;
bool hasPluginProperty(const QString &key) const;
virtual void insertGuiClients(KXMLGUIClient *parent);
virtual void removeGuiClients(KXMLGUIClient *parent);
protected:
virtual void doInitialize() = 0;
private:
QHash<QString, QString> m_properties;
};
} // namespace Akregator
/*
This file is part of Akregator.
SPDX-FileCopyrightText: 2005 Stanislav Karchebny <Stanislav.Karchebny@kdemail.net>
SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
*/
#pragma once
#include "akregatorinterfaces_export.h"
#include <QObject>
class QString;
#include <QStringList>
namespace Akregator
{
namespace Backend
{
class FeedStorage;
/** \brief Storage is the main interface to the article archive. It creates and manages FeedStorage objects handling the article list for a feed.
An archive implementation must implement Storage, FeedStorage and StorageFactory. See mk4storage for an example.
*/
class Storage : public QObject // krazy:exclude=qobject
{
public:
~Storage() override = default;
/** initializes the storage object with given parameters */
virtual void initialize(const QStringList &params) = 0;
/**
* Open storage and prepare it for work.
* @return true on success.
*/
virtual bool open(bool autoCommit = false) = 0;
/**
* Commit changes made in feeds and articles, making them persistent.
* @return true on success.
*/
virtual bool commit() = 0;
/**
* Rollback changes made in feeds and articles, reverting to last committed values.
* @returns true on success.
*/
virtual bool rollback() = 0;
/**
* Closes storage, freeing all allocated resources. Called from destructor, so you don't need to call it directly.
* @return true on success.
*/
virtual void close() = 0;
/**
* @return Article archive for feed at given url.
*/
virtual FeedStorage *archiveFor(const QString &url) = 0;
virtual const FeedStorage *archiveFor(const QString &url) const = 0;
virtual bool autoCommit() const = 0;
/** stores the feed list in the storage backend. This is a fallback for the case that the
feeds.opml file gets corrupted
@param opmlStr the feed list in OPML format
*/
virtual void storeFeedList(const QString &opmlStr) = 0;
virtual QString restoreFeedList() const = 0;
/** returns a list of all feeds (URLs) stored in this archive */
virtual QStringList feeds() const = 0;
};
} // namespace Backend
} // namespace Akregator
/*
This file is part of Akregator.
SPDX-FileCopyrightText: 2005 Frank Osterfeld <osterfeld@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
*/
#pragma once
#include "akregatorinterfaces_export.h"
class QString;
#include <QStringList>
namespace Akregator
{
namespace Backend
{
class Storage;
class AKREGATORINTERFACES_EXPORT StorageFactory
{
public:
virtual ~StorageFactory() = default;
/** identifier of the storage type, like "metakit", "postgres" etc. For use in
configuration files. Must not contain spaces or special characters.
*/
virtual QString key() const = 0;
/** returns the (i18n'd) name of the storage type. */
virtual QString name() const = 0;
/** true if the plugin is configurable via a config dialog */
virtual bool isConfigurable() const = 0;
/** shows the plugin's configuration dialog */
virtual void configure() = 0;
/** creates a storage object with given parameters
@param params list of implementation-specific parameters
*/
virtual Storage *createStorage(const QStringList &params) const = 0;
};
} // namespace Backend
} // namespace Akregator
/*
This file is part of Akregator.
SPDX-FileCopyrightText: 2005 Frank Osterfeld <osterfeld@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
*/
#include "storagefactoryregistry.h"
#include "storagefactory.h"
#include <QString>
namespace Akregator
{
namespace Backend
{
StorageFactoryRegistry *StorageFactoryRegistry::m_instance = nullptr;
StorageFactoryRegistry *StorageFactoryRegistry::self()
{
static StorageFactoryRegistry instance;
if (!m_instance) {
m_instance = &instance;
}
return m_instance;
}
bool StorageFactoryRegistry::registerFactory(StorageFactory *factory, const QString &typestr)
{
if (containsFactory(typestr)) {
return false;
}
m_map[typestr] = factory;
return true;
}
void StorageFactoryRegistry::unregisterFactory(const QString &typestr)
{
m_map.remove(typestr);
}