dde-dock/frame/util/abstractpluginscontroller.cpp
donghualin bc840d233d feat: 加载基本插件
加载pluginmanager插件,其他的插件由pluginmanager插件来加载

Log:
Influence: 插件加载
Task: https://pms.uniontech.com/task-view-222353.html
Change-Id: Ibe3cb59c5e3da27d7547d9bea8e05ebcd03c5a87
2023-01-12 13:51:25 +08:00

206 lines
6.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
*
* Author: sbw <sbw@sbw.so>
*
* Maintainer: sbw <sbw@sbw.so>
*
* 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 3 of the License, or
* 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, see <http://www.gnu.org/licenses/>.
*/
#include "abstractpluginscontroller.h"
#include "pluginsiteminterface.h"
#include "utils.h"
#include "settingconfig.h"
#include "pluginmanagerinterface.h"
#include <DNotifySender>
#include <DSysInfo>
#include <QDebug>
#include <QDir>
#include <QMapIterator>
static const QStringList CompatiblePluginApiList {
"1.1.1",
"1.2",
"1.2.1",
"1.2.2",
DOCK_PLUGIN_API_VERSION
};
AbstractPluginsController::AbstractPluginsController(QObject *parent)
: QObject(parent)
, m_pluginManager(nullptr)
{
qApp->installEventFilter(this);
}
AbstractPluginsController::~AbstractPluginsController()
{
for (auto inter : m_pluginsMap.keys()) {
delete m_pluginsMap.value(inter).value("pluginloader");
m_pluginsMap[inter]["pluginloader"] = nullptr;
m_pluginsMap.remove(inter);
delete inter;
inter = nullptr;
}
}
void AbstractPluginsController::startLoader(PluginLoader *loader)
{
connect(loader, &PluginLoader::finished, loader, &PluginLoader::deleteLater, Qt::QueuedConnection);
connect(loader, &PluginLoader::pluginFounded, this, [ = ](const QString &pluginFile) {
QPair<QString, PluginsItemInterface *> pair;
pair.first = pluginFile;
pair.second = nullptr;
m_pluginLoadMap.insert(pair, false);
});
connect(loader, &PluginLoader::pluginFounded, this, &AbstractPluginsController::loadPlugin, Qt::QueuedConnection);
int delay = Utils::SettingValue("com.deepin.dde.dock", "/com/deepin/dde/dock/", "delay-plugins-time", 0).toInt();
QTimer::singleShot(delay, loader, [ = ] { loader->start(QThread::LowestPriority); });
}
void AbstractPluginsController::displayModeChanged()
{
const Dock::DisplayMode displayMode = qApp->property(PROP_DISPLAY_MODE).value<Dock::DisplayMode>();
const auto inters = m_pluginsMap.keys();
for (auto inter : inters)
inter->displayModeChanged(displayMode);
}
void AbstractPluginsController::positionChanged()
{
const Dock::Position position = qApp->property(PROP_POSITION).value<Dock::Position>();
const auto inters = m_pluginsMap.keys();
for (auto inter : inters)
inter->positionChanged(position);
}
void AbstractPluginsController::loadPlugin(const QString &pluginFile)
{
QPluginLoader *pluginLoader = new QPluginLoader(pluginFile, this);
const QJsonObject &meta = pluginLoader->metaData().value("MetaData").toObject();
const QString &pluginApi = meta.value("api").toString();
bool pluginIsValid = true;
if (pluginApi.isEmpty() || !CompatiblePluginApiList.contains(pluginApi)) {
qDebug() << objectName()
<< "plugin api version not matched! expect versions:" << CompatiblePluginApiList
<< ", got version:" << pluginApi
<< ", the plugin file is:" << pluginFile;
pluginIsValid = false;
}
PluginsItemInterface *interface = qobject_cast<PluginsItemInterface *>(pluginLoader->instance());
if (!interface) {
qDebug() << objectName() << "load plugin failed!!!" << pluginLoader->errorString() << pluginFile;
pluginLoader->unload();
pluginLoader->deleteLater();
pluginIsValid = false;
}
if (!pluginIsValid) {
for (auto &pair : m_pluginLoadMap.keys()) {
if (pair.first == pluginFile) {
m_pluginLoadMap.remove(pair);
}
}
QString notifyMessage(tr("The plugin %1 is not compatible with the system."));
Dtk::Core::DUtil::DNotifySender(notifyMessage.arg(QFileInfo(pluginFile).fileName())).appIcon("dialog-warning").call();
return;
}
QMapIterator<QPair<QString, PluginsItemInterface *>, bool> it(m_pluginLoadMap);
while (it.hasNext()) {
it.next();
if (it.key().first == pluginFile) {
m_pluginLoadMap.remove(it.key());
QPair<QString, PluginsItemInterface *> newPair;
newPair.first = pluginFile;
newPair.second = interface;
m_pluginLoadMap.insert(newPair, false);
break;
}
}
// 保存 PluginLoader 对象指针
QMap<QString, QObject *> interfaceData;
interfaceData["pluginloader"] = pluginLoader;
m_pluginsMap.insert(interface, interfaceData);
PluginManagerInterface * pluginManager = dynamic_cast<PluginManagerInterface *>(interface);
if (pluginManager) {
m_pluginManager = pluginManager;
connect(m_pluginManager, &PluginManagerInterface::pluginLoadFinished, this, &AbstractPluginsController::pluginLoaderFinished);
}
// NOTE(justforlxz): 插件的所有初始化工作都在init函数中进行
// loadPlugin函数是按队列执行的initPlugin函数会有可能导致
// 函数执行被阻塞。
QTimer::singleShot(1, this, [ = ] {
initPlugin(interface);
});
}
void AbstractPluginsController::initPlugin(PluginsItemInterface *interface)
{
if (!interface)
return;
qDebug() << objectName() << "init plugin: " << interface->pluginName();
interface->init(this);
for (const auto &pair : m_pluginLoadMap.keys()) {
if (pair.second == interface)
m_pluginLoadMap.insert(pair, true);
}
bool loaded = true;
for (int i = 0; i < m_pluginLoadMap.keys().size(); ++i) {
if (!m_pluginLoadMap.values()[i]) {
loaded = false;
break;
}
}
qDebug() << objectName() << "init plugin finished: " << interface->pluginName();
}
bool AbstractPluginsController::eventFilter(QObject *object, QEvent *event)
{
if (object != qApp || event->type() != QEvent::DynamicPropertyChange)
return false;
QDynamicPropertyChangeEvent *const dpce = static_cast<QDynamicPropertyChangeEvent *>(event);
const QString propertyName = dpce->propertyName();
if (propertyName == PROP_POSITION)
positionChanged();
else if (propertyName == PROP_DISPLAY_MODE)
displayModeChanged();
return false;
}
PluginManagerInterface *AbstractPluginsController::pluginManager() const
{
return m_pluginManager;
}