[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [plasma-framework] src/declarativeimports/calendar: [calendar] Move the plugins handling to a separa
From:       Martin Klapetek <mklapetek () kde ! org>
Date:       2015-11-16 16:55:20
Message-ID: E1ZyN3o-0006OB-Ih () scm ! kde ! org
[Download RAW message or body]

Git commit d0d0a27bac0ff9ee84320dff1ff8b42d9696dccf by Martin Klapetek.
Committed on 16/11/2015 at 16:49.
Pushed by mklapetek into branch 'master'.

[calendar] Move the plugins handling to a separate class

This is also made a QML singleton that will be used for the applet
config view where it will add the plugin configs once we add that
possibility.

The same instance is then set to the DaysModel from QML.

REVIEW: 125951

M  +1    -0    src/declarativeimports/calendar/CMakeLists.txt
M  +13   -4    src/declarativeimports/calendar/calendarplugin.cpp
M  +35   -48   src/declarativeimports/calendar/daysmodel.cpp
M  +6    -2    src/declarativeimports/calendar/daysmodel.h
A  +248  -0    src/declarativeimports/calendar/eventpluginsmanager.cpp     [License: \
GPL (v2+)] A  +76   -0    src/declarativeimports/calendar/eventpluginsmanager.h     \
[License: GPL (v2+)] M  +4    -0    src/declarativeimports/calendar/qml/MonthView.qml

http://commits.kde.org/plasma-framework/d0d0a27bac0ff9ee84320dff1ff8b42d9696dccf

diff --git a/src/declarativeimports/calendar/CMakeLists.txt \
b/src/declarativeimports/calendar/CMakeLists.txt index 7497bda..4aac02d 100644
--- a/src/declarativeimports/calendar/CMakeLists.txt
+++ b/src/declarativeimports/calendar/CMakeLists.txt
@@ -8,6 +8,7 @@ set(calendar_SRCS
     #datetimerangefiltermodel.cpp
     daysmodel.cpp
     eventdatadecorator.cpp
+    eventpluginsmanager.cpp
 )
 
 add_library(calendarplugin SHARED ${calendar_SRCS})
diff --git a/src/declarativeimports/calendar/calendarplugin.cpp \
b/src/declarativeimports/calendar/calendarplugin.cpp index a4014bd..6014398 100644
--- a/src/declarativeimports/calendar/calendarplugin.cpp
+++ b/src/declarativeimports/calendar/calendarplugin.cpp
@@ -21,11 +21,22 @@
 #include "calendardata.h"
 #include "calendar.h"
 #include "eventdatadecorator.h"
+#include "eventpluginsmanager.h"
 
 #include <QtQml>
-#include <QAbstractItemModel>
+#include <QQmlEngine>
 #include <QAbstractListModel>
 
+static QObject *event_plugins_manager_provider(QQmlEngine *engine, QJSEngine \
*scriptEngine) +{
+    Q_UNUSED(scriptEngine)
+
+    EventPluginsManager *manager = new EventPluginsManager();
+    engine->setObjectOwnership(manager, QQmlEngine::CppOwnership);
+
+    return manager;
+}
+
 void CalendarPlugin::registerTypes(const char *uri)
 {
     Q_ASSERT(uri == QLatin1String("org.kde.plasma.calendar"));
@@ -34,7 +45,5 @@ void CalendarPlugin::registerTypes(const char *uri)
     qmlRegisterType<QAbstractItemModel>();
     qmlRegisterType<QAbstractListModel>();
     qmlRegisterUncreatableType<EventDataDecorator>();
+    qmlRegisterSingletonType<EventPluginsManager>(uri, 2, 0, "EventPluginsManager", \
event_plugins_manager_provider);  }
-
-//Q_EXPORT_PLUGIN2(calendarplugin, CalendarPlugin)
-#include "moc_calendarplugin.cpp"
diff --git a/src/declarativeimports/calendar/daysmodel.cpp \
b/src/declarativeimports/calendar/daysmodel.cpp index 6572321..8500b1f 100644
--- a/src/declarativeimports/calendar/daysmodel.cpp
+++ b/src/declarativeimports/calendar/daysmodel.cpp
@@ -18,60 +18,18 @@
 */
 
 #include "daysmodel.h"
+#include "eventdatadecorator.h"
+#include "eventpluginsmanager.h"
 
 #include <QDebug>
 #include <QByteArray>
-#include <QPluginLoader>
 #include <QDir>
-#include <QCoreApplication>
 
 DaysModel::DaysModel(QObject *parent) :
     QAbstractListModel(parent),
-    m_agendaNeedsUpdate(false)
+    m_agendaNeedsUpdate(false),
+    m_pluginsManager(0)
 {
-    QString pluginPath;
-
-    const QStringList paths = QCoreApplication::libraryPaths();
-    Q_FOREACH (const QString &libraryPath, paths) {
-        const QString path(libraryPath + QStringLiteral("/plasmacalendarplugins"));
-        QDir dir(path);
-
-        if (!dir.exists()) {
-            continue;
-        }
-
-        QStringList entryList = dir.entryList(QDir::Files | QDir::NoDotAndDotDot);
-        Q_FOREACH (const QString &fileName, entryList) {
-            QPluginLoader loader(dir.absoluteFilePath(fileName));
-
-            if (!loader.load()) {
-                qWarning() << "Could not create Plasma Calendar Plugin: " << \
                pluginPath;
-                qWarning() << loader.errorString();
-                continue;
-            }
-
-            QObject *obj = loader.instance();
-            if (obj) {
-                Plasma::CalendarEventsPlugin *eventsPlugin = \
                qobject_cast<Plasma::CalendarEventsPlugin*>(obj);
-                if (eventsPlugin) {
-                    qDebug() << "Adding Calendar plugin" << eventsPlugin;
-                    connect(eventsPlugin, &Plasma::CalendarEventsPlugin::dataReady,
-                            this, &DaysModel::onDataReady);
-                    connect(eventsPlugin, \
                &Plasma::CalendarEventsPlugin::eventModified,
-                            this, &DaysModel::onEventModified);
-                    connect(eventsPlugin, \
                &Plasma::CalendarEventsPlugin::eventRemoved,
-                            this, &DaysModel::onEventRemoved);
-                    m_eventPlugins << eventsPlugin;
-                } else {
-                    // not our/valid plugin, so unload it
-                    loader.unload();
-                }
-            } else {
-                loader.unload();
-            }
-        }
-    }
-
     QHash<int, QByteArray> roleNames;
 
     roleNames.insert(isCurrent,              "isCurrent");
@@ -142,8 +100,10 @@ void DaysModel::update()
 
     const QDate modelFirstDay(m_data->at(0).yearNumber, m_data->at(0).monthNumber, \
m_data->at(0).dayNumber);  
-    Q_FOREACH (Plasma::CalendarEventsPlugin *eventsPlugin, m_eventPlugins) {
-        eventsPlugin->loadEventsForDateRange(modelFirstDay, \
modelFirstDay.addDays(42)); +    if (m_pluginsManager) {
+        Q_FOREACH (Plasma::CalendarEventsPlugin *eventsPlugin, \
m_pluginsManager->plugins()) { +            \
eventsPlugin->loadEventsForDateRange(modelFirstDay, modelFirstDay.addDays(42)); +     \
}  }
 }
 
@@ -245,3 +205,30 @@ QModelIndex DaysModel::indexForDate(const QDate &date)
 
     return createIndex(daysTo, 0);
 }
+
+void DaysModel::setPluginsManager(QObject *manager)
+{
+    EventPluginsManager *m = qobject_cast<EventPluginsManager*>(manager);
+
+    if (!m) {
+        return;
+    }
+
+    if (m_pluginsManager != 0) {
+        m_pluginsManager->deleteLater();
+        m_pluginsManager = 0;
+    }
+
+    m_pluginsManager = m;
+
+    connect(m_pluginsManager, &EventPluginsManager::dataReady,
+            this, &DaysModel::onDataReady);
+    connect(m_pluginsManager, &EventPluginsManager::eventModified,
+            this, &DaysModel::onEventModified);
+    connect(m_pluginsManager, &EventPluginsManager::eventRemoved,
+            this, &DaysModel::onEventRemoved);
+    connect(m_pluginsManager, &EventPluginsManager::pluginsChanged,
+            this, &DaysModel::update);
+
+    update();
+}
diff --git a/src/declarativeimports/calendar/daysmodel.h \
b/src/declarativeimports/calendar/daysmodel.h index 8d97c79..9f44390 100644
--- a/src/declarativeimports/calendar/daysmodel.h
+++ b/src/declarativeimports/calendar/daysmodel.h
@@ -23,13 +23,14 @@
 #include <QAbstractListModel>
 
 #include "daydata.h"
-#include "eventdatadecorator.h"
-
 #include "plasmacalendarintegration/calendareventsplugin.h"
 
+class EventPluginsManager;
+
 class DaysModel : public QAbstractListModel
 {
     Q_OBJECT
+
 public:
     enum Roles {
         isCurrent = Qt::UserRole + 1,
@@ -49,6 +50,8 @@ public:
     QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
     void update();
 
+    Q_INVOKABLE void setPluginsManager(QObject *manager);
+
     Q_INVOKABLE QList<QObject*> eventsForDate(const QDate &date);
 
 Q_SIGNALS:
@@ -62,6 +65,7 @@ private Q_SLOTS:
 private:
     QModelIndex indexForDate(const QDate &date);
 
+    EventPluginsManager *m_pluginsManager;
     QList<DayData> *m_data;
     QList<QObject*> m_qmlData;
     QDate m_lastRequestedAgendaDate;
diff --git a/src/declarativeimports/calendar/eventpluginsmanager.cpp \
b/src/declarativeimports/calendar/eventpluginsmanager.cpp new file mode 100644
index 0000000..20f648f
--- /dev/null
+++ b/src/declarativeimports/calendar/eventpluginsmanager.cpp
@@ -0,0 +1,248 @@
+/*
+    Copyright (C) 2015 Martin Klapetek <mklapetek@kde.org>
+
+    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.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+*/
+
+#include "eventpluginsmanager.h"
+#include "plasmacalendarintegration/calendareventsplugin.h"
+
+#include <QCoreApplication>
+#include <QAbstractListModel>
+#include <QJsonObject>
+#include <QPluginLoader>
+#include <QDir>
+#include <QDebug>
+
+class EventPluginsModel : public QAbstractListModel
+{
+    Q_OBJECT
+public:
+    EventPluginsModel(EventPluginsManager *manager) : QAbstractListModel(manager)
+    {
+        m_manager = manager;
+        m_roles = QAbstractListModel::roleNames();
+        m_roles.insert(Qt::EditRole, QByteArrayLiteral("checked"));
+        m_roles.insert(Qt::UserRole, QByteArrayLiteral("configUi"));
+    };
+
+    // make these two available to the manager
+    void beginResetModel()
+    {
+        QAbstractListModel::beginResetModel();
+    }
+
+    void endResetModel()
+    {
+        QAbstractListModel::endResetModel();
+    }
+
+    virtual QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE
+    {
+        return m_roles;
+    }
+
+    Q_INVOKABLE int rowCount(const QModelIndex &parent = QModelIndex()) const \
Q_DECL_OVERRIDE +    {
+        Q_UNUSED(parent);
+        return m_manager->m_availablePlugins.size();
+    }
+
+    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const \
Q_DECL_OVERRIDE +    {
+        if (!index.isValid() && !m_manager) {
+            return QVariant();
+        }
+
+        const QString currentPlugin = \
m_manager->m_availablePlugins.keys().at(index.row()); +        const QJsonObject \
metadata = m_manager->m_availablePlugins.value(currentPlugin).value(QStringLiteral("MetaData")).toObject();
 +
+        switch (role) {
+            case Qt::DisplayRole:
+                return metadata.value(QStringLiteral("Name"));
+            case Qt::DecorationRole:
+                return metadata.value(QStringLiteral("Icon"));
+            case Qt::UserRole:
+            {
+                // The currentPlugin path contains the full path including
+                // the plugin filename, so it needs to be cut off from the last '/'
+                const QStringRef pathRef = \
currentPlugin.leftRef(currentPlugin.lastIndexOf('/')); +                const QString \
qmlFilePath = metadata.value(QStringLiteral("ConfigUi")).toString(); +                \
return QString(pathRef % '/' % qmlFilePath); +            }
+            case Qt::EditRole:
+                return m_manager->m_enabledPlugins.contains(currentPlugin);
+        }
+
+        return QVariant();
+
+    }
+
+    bool setData(const QModelIndex &index, const QVariant &value, int role = \
Qt::EditRole) Q_DECL_OVERRIDE +    {
+        if (role != Qt::EditRole || !index.isValid()) {
+            return false;
+        }
+
+        bool enabled = value.toBool();
+        const QString pluginPath = \
m_manager->m_availablePlugins.keys().at(index.row()); +
+        if (enabled) {
+            if (!m_manager->m_enabledPlugins.contains(pluginPath)) {
+                m_manager->m_enabledPlugins << pluginPath;
+            }
+        } else {
+            m_manager->m_enabledPlugins.removeOne(pluginPath);
+        }
+
+        emit dataChanged(index, index);
+
+        return true;
+    }
+
+    Q_INVOKABLE QVariant get(int row, const QByteArray &role)
+    {
+        return data(createIndex(row, 0), roleNames().key(role));
+    }
+
+private:
+    EventPluginsManager *m_manager;
+    QHash<int, QByteArray> m_roles;
+};
+
+EventPluginsManager::EventPluginsManager(QObject *parent)
+    : QObject(parent)
+{
+    QString pluginPath;
+
+    // First of all get a list of available plugins
+    // and get their metadata. This alone is enough
+    // for the applet config to work
+    const QStringList paths = QCoreApplication::libraryPaths();
+    Q_FOREACH (const QString &libraryPath, paths) {
+        const QString path(libraryPath + QStringLiteral("/plasmacalendarplugins"));
+        QDir dir(path);
+
+        if (!dir.exists()) {
+            continue;
+        }
+
+        QStringList entryList = dir.entryList(QDir::Files | QDir::NoDotAndDotDot);
+
+        Q_FOREACH (const QString &fileName, entryList) {
+            const QString absolutePath = dir.absoluteFilePath(fileName);
+            QPluginLoader loader(absolutePath);
+            // Load only our own plugins
+            if (loader.metaData().value(QStringLiteral("IID")) == \
QLatin1String("org.kde.plasma.CalendarEventsPlugin")) { +                \
m_availablePlugins.insert(absolutePath, loader.metaData()); +            }
+        }
+    }
+
+    m_model = new EventPluginsModel(this);
+    Q_EMIT pluginsChanged();
+}
+
+EventPluginsManager::~EventPluginsManager()
+{
+    qDeleteAll(m_plugins);
+}
+
+void EventPluginsManager::populateEnabledPluginsList(const QStringList &pluginsList)
+{
+    m_model->beginResetModel();
+    m_enabledPlugins = pluginsList;
+    m_model->endResetModel();
+}
+
+void EventPluginsManager::setEnabledPlugins(QStringList &pluginsList)
+{
+    m_model->beginResetModel();
+    m_enabledPlugins = pluginsList;
+
+    // Remove all already loaded plugins from the pluginsList
+    // and unload those plugins that are not in the pluginsList
+    auto i = m_plugins.begin();
+    while (i != m_plugins.end()) {
+        const QString pluginPath = (*i)->property("pluginPath").toString();
+        if (pluginsList.contains(pluginPath)) {
+            pluginsList.removeAll(pluginPath);
+            ++i;
+        } else {
+            (*i)->deleteLater();
+            i = m_plugins.erase(i);
+        }
+    }
+
+    // Now load all the plugins left in pluginsList
+    Q_FOREACH (const QString &pluginPath, pluginsList) {
+        loadPlugin(pluginPath);
+    }
+
+    m_model->endResetModel();
+    Q_EMIT pluginsChanged();
+}
+
+QStringList EventPluginsManager::enabledPlugins() const
+{
+    return m_enabledPlugins;
+}
+
+void EventPluginsManager::loadPlugin(const QString &absolutePath)
+{
+    QPluginLoader loader(absolutePath);
+
+    if (!loader.load()) {
+        qWarning() << "Could not create Plasma Calendar Plugin: " << absolutePath;
+        qWarning() << loader.errorString();
+        return;
+    }
+
+    QObject *obj = loader.instance();
+    if (obj) {
+        Plasma::CalendarEventsPlugin *eventsPlugin = \
qobject_cast<Plasma::CalendarEventsPlugin*>(obj); +        if (eventsPlugin) {
+            qDebug() << "Loading Calendar plugin" << eventsPlugin;
+            eventsPlugin->setProperty("pluginPath", absolutePath);
+            m_plugins << eventsPlugin;
+
+            // Connect the relay signals
+            connect(eventsPlugin, &Plasma::CalendarEventsPlugin::dataReady,
+                    this, &EventPluginsManager::dataReady);
+            connect(eventsPlugin, &Plasma::CalendarEventsPlugin::eventModified,
+                    this, &EventPluginsManager::eventModified);
+            connect(eventsPlugin, &Plasma::CalendarEventsPlugin::eventRemoved,
+                    this, &EventPluginsManager::eventRemoved);
+        } else {
+            // not our/valid plugin, so unload it
+            loader.unload();
+        }
+    } else {
+        loader.unload();
+    }
+}
+
+QList<Plasma::CalendarEventsPlugin*> EventPluginsManager::plugins() const
+{
+    return m_plugins;
+}
+
+QAbstractListModel* EventPluginsManager::pluginsModel() const
+{
+    return m_model;
+}
+
+#include "eventpluginsmanager.moc"
diff --git a/src/declarativeimports/calendar/eventpluginsmanager.h \
b/src/declarativeimports/calendar/eventpluginsmanager.h new file mode 100644
index 0000000..d736487
--- /dev/null
+++ b/src/declarativeimports/calendar/eventpluginsmanager.h
@@ -0,0 +1,76 @@
+/*
+    Copyright (C) 2015 Martin Klapetek <mklapetek@kde.org>
+
+    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.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+*/
+
+#ifndef EVENTPLUGINSMANAGER_H
+#define EVENTPLUGINSMANAGER_H
+
+#include <QObject>
+#include <QMap>
+
+namespace Plasma {
+class CalendarEventsPlugin;
+class EventData;
+}
+class EventPluginsModel;
+class QAbstractListModel;
+
+class EventPluginsManager : public QObject
+{
+    Q_OBJECT
+    Q_PROPERTY(QAbstractListModel *model READ pluginsModel NOTIFY pluginsChanged)
+    Q_PROPERTY(QStringList enabledPlugins READ enabledPlugins WRITE \
setEnabledPlugins NOTIFY pluginsChanged) +
+public:
+    EventPluginsManager(QObject *parent = 0);
+    ~EventPluginsManager();
+
+    QList<Plasma::CalendarEventsPlugin*> plugins() const;
+    QAbstractListModel* pluginsModel() const;
+
+    // This is a helper function to set which plugins
+    // are enabled without needing to go through setEnabledPlugins
+    // which also loads the plugins; from the Applet config
+    // the plugins are not required to be actually loaded
+    Q_INVOKABLE void populateEnabledPluginsList(const QStringList &pluginsList);
+
+    void setEnabledPlugins(QStringList &pluginsList);
+    QStringList enabledPlugins() const;
+
+Q_SIGNALS:
+    void pluginsChanged();
+
+    // These three signals below are used for relaying the
+    // plugin signals so that the EventPluginsManager don't
+    // have to worry about connecting to newly loaded plugins
+    void dataReady(const QMultiHash<QDate, Plasma::EventData> &data);
+    void eventModified(const Plasma::EventData &modifiedEvent);
+    void eventRemoved(const QString &uid);
+
+private:
+    void loadPlugin(const QString &absolutePath);
+
+    friend class EventPluginsModel;
+    EventPluginsModel *m_model;
+    QList<Plasma::CalendarEventsPlugin*> m_plugins;
+    QMap<QString, QJsonObject> m_availablePlugins;
+    QStringList m_enabledPlugins;
+};
+
+#endif
+
diff --git a/src/declarativeimports/calendar/qml/MonthView.qml \
b/src/declarativeimports/calendar/qml/MonthView.qml index 535b6e4..59e084d 100644
--- a/src/declarativeimports/calendar/qml/MonthView.qml
+++ b/src/declarativeimports/calendar/qml/MonthView.qml
@@ -123,6 +123,10 @@ PinchArea {
         firstDayOfWeek: Qt.locale().firstDayOfWeek
         today: root.today
 
+        Component.onCompleted: {
+            daysModel.setPluginsManager(EventPluginsManager);
+        }
+
         onYearChanged: {
             updateYearOverview()
             updateDecadeOverview()


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic