fix: 修复时尚模式下无法显示电源按钮的问题

原因:电源按钮只会加载一次,在时尚模式下已经加载过,导致在高效模式下没有加载到任务栏的controller中
解决方案:将加载电源按钮的controller用一个单例的代理类来实现,FixedPluginController和DockPluginsController同时引用这个类来加载同一个插件

Log: 解决时尚模式下无法显示电源按钮的问题
Influence: 任务栏-查看高效模式下电源插件是否加载
Bug: https://pms.uniontech.com/bug-view-132733.html
Change-Id: I80d0cb9c87e6e1a478410f53a35ccfce344677ea
This commit is contained in:
donghualin 2022-05-27 15:09:15 +08:00
parent 7c3db6c9be
commit 9a81886b6a
10 changed files with 338 additions and 112 deletions

View File

@ -20,6 +20,7 @@
*/
#include "dockpluginscontroller.h"
#include "proxyplugincontroller.h"
#include "pluginsiteminterface.h"
#include "traypluginitem.h"
@ -31,6 +32,13 @@ DockPluginsController::DockPluginsController(QObject *parent)
: AbstractPluginsController(parent)
{
setObjectName("DockPlugin");
ProxyPluginController::instance()->addProxyInterface(this);
}
DockPluginsController::~DockPluginsController()
{
ProxyPluginController::instance()->removeProxyInterface(this);
}
void DockPluginsController::itemAdded(PluginsItemInterface *const itemInter, const QString &itemKey)
@ -43,10 +51,10 @@ void DockPluginsController::itemAdded(PluginsItemInterface *const itemInter, con
return;
// 取 plugin api
QPluginLoader *pluginLoader = qobject_cast<QPluginLoader*>(mPluginsMap[itemInter].value("pluginloader"));
if (!pluginLoader) {
QPluginLoader *pluginLoader = ProxyPluginController::instance()->pluginLoader(itemInter);
if (!pluginLoader)
return;
}
const QJsonObject &meta = pluginLoader->metaData().value("MetaData").toObject();
const QString &pluginApi = meta.value("api").toString();
@ -135,30 +143,5 @@ void DockPluginsController::requestSetAppletVisible(PluginsItemInterface *const
void DockPluginsController::startLoader()
{
loadLocalPlugins();
loadSystemPlugins();
}
void DockPluginsController::loadLocalPlugins()
{
QString pluginsDir(QString("%1/.local/lib/dde-dock/plugins/").arg(QDir::homePath()));
if (!QDir(pluginsDir).exists()) {
return;
}
qDebug() << "using dock local plugins dir:" << pluginsDir;
AbstractPluginsController::startLoader(new PluginLoader(pluginsDir, this));
}
void DockPluginsController::loadSystemPlugins()
{
QString pluginsDir(qApp->applicationDirPath() + "/../plugins");
#ifndef QT_DEBUG
pluginsDir = "/usr/lib/dde-dock/plugins";
#endif
qDebug() << "using dock plugins dir:" << pluginsDir;
AbstractPluginsController::startLoader(new PluginLoader(pluginsDir, this));
ProxyPluginController::instance()->startLoader();
}

View File

@ -43,6 +43,7 @@ class DockPluginsController : public AbstractPluginsController
public:
explicit DockPluginsController(QObject *parent = nullptr);
~DockPluginsController() override;
// implements PluginProxyInterface
void itemAdded(PluginsItemInterface * const itemInter, const QString &itemKey) override;
@ -59,10 +60,6 @@ signals:
void pluginItemRemoved(PluginsItem *pluginItem) const;
void pluginItemUpdated(PluginsItem *pluginItem) const;
void trayVisableCountChanged(const int &count) const;
private:
void loadLocalPlugins();
void loadSystemPlugins();
};
#endif // DOCKPLUGINSCONTROLLER_H

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
*
* Author: donghualin <donghualin@uniontech.com>
*
* Maintainer: donghualin <donghualin@uniontech.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 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 "fixedplugincontroller.h"
#include "utils.h"
#include "proxyplugincontroller.h"
#include "systempluginwindow.h"
FixedPluginController::FixedPluginController(QObject *parent)
: AbstractPluginsController(parent)
{
setObjectName("FixedPluginController");
ProxyPluginController::instance()->addProxyInterface(this, QStringList("shutdown"));
}
FixedPluginController::~FixedPluginController()
{
ProxyPluginController::instance()->removeProxyInterface(this);
}
void FixedPluginController::itemAdded(PluginsItemInterface * const itemInter, const QString &itemKey)
{
StretchPluginsItem *item = new StretchPluginsItem(itemInter, itemKey);
m_pluginItems << item;
Q_EMIT pluginItemInserted(item);
}
void FixedPluginController::itemUpdate(PluginsItemInterface * const itemInter, const QString &)
{
for (StretchPluginsItem *item : m_pluginItems) {
if (item->pluginInter() == itemInter) {
Q_EMIT pluginItemUpdated(item);
break;
}
}
}
void FixedPluginController::itemRemoved(PluginsItemInterface * const itemInter, const QString &)
{
for (StretchPluginsItem *item : m_pluginItems) {
if (item->pluginInter() == itemInter) {
m_pluginItems.removeOne(item);
Q_EMIT pluginItemRemoved(item);
item->deleteLater();
break;
}
}
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
*
* Author: donghualin <donghualin@uniontech.com>
*
* Maintainer: donghualin <donghualin@uniontech.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 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/>.
*/
#ifndef FIXEDPLUGINCONTROLLER_H
#define FIXEDPLUGINCONTROLLER_H
#include "abstractpluginscontroller.h"
class StretchPluginsItem;
class FixedPluginController : public AbstractPluginsController
{
Q_OBJECT
public:
explicit FixedPluginController(QObject *parent = nullptr);
~FixedPluginController() override;
Q_SIGNALS:
void pluginItemInserted(StretchPluginsItem *);
void pluginItemRemoved(StretchPluginsItem *);
void pluginItemUpdated(StretchPluginsItem *);
protected:
void itemAdded(PluginsItemInterface * const itemInter, const QString &itemKey) override;
void itemUpdate(PluginsItemInterface * const itemInter, const QString &) override;
void itemRemoved(PluginsItemInterface * const itemInter, const QString &) override;
void requestWindowAutoHide(PluginsItemInterface * const, const QString &, const bool) override {}
void requestRefreshWindowVisible(PluginsItemInterface * const, const QString &) override {}
void requestSetAppletVisible(PluginsItemInterface * const, const QString &, const bool) override {}
private:
QList<StretchPluginsItem *> m_pluginItems;
};
#endif // FIXEDPLUGINCONTROLLER_H

View File

@ -0,0 +1,127 @@
/*
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
*
* Author: donghualin <donghualin@uniontech.com>
*
* Maintainer: donghualin <donghualin@uniontech.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 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 "proxyplugincontroller.h"
#include "pluginsiteminterface.h"
QMap<int, ProxyPluginController *> ProxyPluginController::m_instances = {};
// 该方法用来设置所有的需要加载的插件的路径信息
static QMap<int, QList<QStringList>> getPluginPaths()
{
QList<QStringList> pluginPaths;
pluginPaths << QStringList{ QString("%1/.local/lib/dde-dock/plugins/").arg(QDir::homePath()) }
<< QStringList{ QString(qApp->applicationDirPath() + "/../plugins"),
QString("/usr/lib/dde-dock/plugins") };
QMap<int, QList<QStringList>> plugins;
plugins[FIXEDSYSTEMPLUGIN] = pluginPaths;
return plugins;
}
// 该方法根据当前加载插件的类型来生成对应的单例的类
ProxyPluginController *ProxyPluginController::instance(int instanceKey)
{
static QMap<int, QList<QStringList>> pluginLoadInfos = getPluginPaths();
if (m_instances.contains(instanceKey))
return m_instances.value(instanceKey);
// 生成单例类,获取加载插件的路径信息
ProxyPluginController *controller = new ProxyPluginController();
controller->m_dirs = (pluginLoadInfos.contains(instanceKey) ? pluginLoadInfos[instanceKey] : QList<QStringList>());
m_instances[instanceKey] = controller;
return controller;
}
// 新增要使用的控制器,第二个参数表示当前控制器需要加载的插件名称,为空表示加载所有插件
void ProxyPluginController::addProxyInterface(AbstractPluginsController *interface, const QStringList &pluginNames)
{
if (!m_interfaces.contains(interface))
m_interfaces[interface] = pluginNames;
}
void ProxyPluginController::removeProxyInterface(AbstractPluginsController *interface)
{
if (m_interfaces.contains(interface))
m_interfaces.remove(interface);
}
ProxyPluginController::ProxyPluginController(QObject *parent)
: AbstractPluginsController(parent)
{
}
QPluginLoader *ProxyPluginController::pluginLoader(PluginsItemInterface * const itemInter)
{
QMap<PluginsItemInterface *, QMap<QString, QObject *> > &plugin = pluginsMap();
if (plugin.contains(itemInter))
return qobject_cast<QPluginLoader *>(plugin[itemInter].value("pluginloader"));
return nullptr;
}
void ProxyPluginController::itemAdded(PluginsItemInterface * const itemInter, const QString &itemKey)
{
// 只有当前的controll设置的过滤名称包含当前插件的名称或者过滤名称为空才新增当前插件
QList<AbstractPluginsController *> pluginKeys = m_interfaces.keys();
for (AbstractPluginsController *interface: pluginKeys) {
const QStringList &filterNames = m_interfaces[interface];
if (filterNames.isEmpty() || filterNames.contains(itemInter->pluginName()))
interface->itemAdded(itemInter, itemKey);
}
}
void ProxyPluginController::itemUpdate(PluginsItemInterface * const itemInter, const QString &itemKey)
{
QList<AbstractPluginsController *> pluginKeys = m_interfaces.keys();
for (AbstractPluginsController *interface: pluginKeys) {
const QStringList &filterNames = m_interfaces[interface];
if (filterNames.isEmpty() || filterNames.contains(itemInter->pluginName()))
interface->itemUpdate(itemInter, itemKey);
}
}
void ProxyPluginController::itemRemoved(PluginsItemInterface * const itemInter, const QString &itemKey)
{
QList<AbstractPluginsController *> pluginKeys = m_interfaces.keys();
for (AbstractPluginsController *interface: pluginKeys) {
const QStringList &filterNames = m_interfaces[interface];
if (filterNames.isEmpty() || filterNames.contains(itemInter->pluginName()))
interface->itemRemoved(itemInter, itemKey);
}
}
void ProxyPluginController::startLoader()
{
QDir dir;
for (const QStringList &pluginPaths : m_dirs) {
QString loadPath;
for (const QString &pluginPath : pluginPaths) {
if (!dir.exists(pluginPath))
continue;
loadPath = pluginPath;
break;
}
if (!loadPath.isEmpty())
AbstractPluginsController::startLoader(new PluginLoader(loadPath, this));
}
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
*
* Author: donghualin <donghualin@uniontech.com>
*
* Maintainer: donghualin <donghualin@uniontech.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 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/>.
*/
#ifndef PROXYPLUGINCONTROLLER_H
#define PROXYPLUGINCONTROLLER_H
#include "abstractpluginscontroller.h"
class PluginsItemInterface;
// 加载的插件的类型
#define FIXEDSYSTEMPLUGIN 1
// 该类是一个底层用来加载系统插件的类DockPluginsController和
// FixedPluginController类都是通过这个类来加载系统插件的
// 该类做成一个单例,因为理论上一个插件只允许被加载一次,但是对于电源插件来说,
// 电源插件在高效模式和特效模式下都需要显示,因此,此类用于加载插件,然后分发到不同的
// 上层控制器中
class ProxyPluginController : public AbstractPluginsController
{
Q_OBJECT
public:
static ProxyPluginController *instance(int instanceKey = FIXEDSYSTEMPLUGIN);
void addProxyInterface(AbstractPluginsController *interface, const QStringList &pluginNames = QStringList());
void removeProxyInterface(AbstractPluginsController *interface);
void startLoader();
QPluginLoader *pluginLoader(PluginsItemInterface * const itemInter);
protected:
explicit ProxyPluginController(QObject *parent = nullptr);
~ProxyPluginController() override {}
void itemAdded(PluginsItemInterface * const itemInter, const QString &itemKey) override;
void itemUpdate(PluginsItemInterface * const itemInter, const QString &itemKey) override;
void itemRemoved(PluginsItemInterface * const itemInter, const QString &itemKey) override;
void requestWindowAutoHide(PluginsItemInterface * const, const QString &, const bool) override {}
void requestRefreshWindowVisible(PluginsItemInterface * const, const QString &) override {}
void requestSetAppletVisible(PluginsItemInterface * const, const QString &, const bool) override {}
private:
static QMap<int, ProxyPluginController *> m_instances;
QMap<AbstractPluginsController *, QStringList> m_interfaces;
QList<QStringList> m_dirs;
};
#endif // PROXYPLUGINCONTROLLER_H

View File

@ -48,6 +48,10 @@ public:
const QVariant getValue(PluginsItemInterface *const itemInter, const QString &key, const QVariant& fallback = QVariant()) override;
void removeValue(PluginsItemInterface * const itemInter, const QStringList &keyList) override;
void itemAdded(PluginsItemInterface * const, const QString &) override {}
void itemUpdate(PluginsItemInterface * const, const QString &) override {}
void itemRemoved(PluginsItemInterface * const, const QString &) override {}
signals:
void pluginLoaderFinished();

View File

@ -275,6 +275,8 @@ void MainPanelControl::addTrayAreaItem(int index, QWidget *wdg)
{
m_tray = static_cast<TrayPluginItem *>(wdg);
m_trayAreaLayout->insertWidget(index, wdg);
if (m_tray)
m_tray->installEventFilter(this);
}
/**往插件区域添加应用,保存回收站插件指针对象
@ -670,6 +672,14 @@ void MainPanelControl::dragMoveEvent(QDragMoveEvent *e)
bool MainPanelControl::eventFilter(QObject *watched, QEvent *event)
{
// 在从时尚模式切换到高效模式的时候,
// m_tray子部件会调整高度此时会触发m_tray调整尺寸
// 但是子部件的模式变化函数在FashionTrayItem部件中的
// NormalContainer部件尺寸变化完成之前就已经结束导致
// NormalContainer没有更新自己的尺寸引起插件区域拥挤
if (m_tray && watched == m_tray && event->type() == QEvent::Resize)
m_tray->pluginItem()->displayModeChanged(m_dislayMode);
// 更新应用区域大小和任务栏图标大小
if (watched == m_appAreaSonWidget) {
switch (event->type()) {

View File

@ -22,6 +22,7 @@
#include "systemplugincontroller.h"
#include "systempluginitem.h"
#include "dockpluginscontroller.h"
#include "fixedplugincontroller.h"
#include <DListView>
#include <QBoxLayout>
@ -43,7 +44,6 @@ SystemPluginWindow::SystemPluginWindow(QWidget *parent)
connect(m_pluginController, &FixedPluginController::pluginItemInserted, this, &SystemPluginWindow::onPluginItemAdded);
connect(m_pluginController, &FixedPluginController::pluginItemRemoved, this, &SystemPluginWindow::onPluginItemRemoved);
connect(m_pluginController, &FixedPluginController::pluginItemUpdated, this, &SystemPluginWindow::onPluginItemUpdated);
QMetaObject::invokeMethod(m_pluginController, &FixedPluginController::startLoader, Qt::QueuedConnection);
}
SystemPluginWindow::~SystemPluginWindow()
@ -140,57 +140,6 @@ void SystemPluginWindow::onPluginItemUpdated(StretchPluginsItem *pluginItem)
pluginItem->update();
}
// can loader plugins
FixedPluginController::FixedPluginController(QObject *parent)
: AbstractPluginsController(parent)
{
setObjectName("FixedPluginController");
}
void FixedPluginController::itemAdded(PluginsItemInterface * const itemInter, const QString &itemKey)
{
StretchPluginsItem *item = new StretchPluginsItem(itemInter, itemKey);
m_pluginItems << item;
Q_EMIT pluginItemInserted(item);
}
void FixedPluginController::itemUpdate(PluginsItemInterface * const itemInter, const QString &)
{
for (StretchPluginsItem *item : m_pluginItems) {
if (item->pluginInter() == itemInter) {
Q_EMIT pluginItemUpdated(item);
break;
}
}
}
void FixedPluginController::itemRemoved(PluginsItemInterface * const itemInter, const QString &)
{
for (StretchPluginsItem *item : m_pluginItems) {
if (item->pluginInter() == itemInter) {
m_pluginItems.removeOne(item);
Q_EMIT pluginItemRemoved(item);
item->deleteLater();
break;
}
}
}
bool FixedPluginController::needLoad(PluginsItemInterface *itemInter)
{
return (itemInter->pluginName().compare("shutdown") == 0);
}
void FixedPluginController::startLoader()
{
QString pluginsDir(qApp->applicationDirPath() + "/../plugins");
QDir dir(pluginsDir);
if (!dir.exists())
pluginsDir = "/usr/lib/dde-dock/plugins";
AbstractPluginsController::startLoader(new PluginLoader(pluginsDir, this));
}
#define ICONSIZE 20
#define ICONTEXTSPACE 6
#define PLUGIN_ITEM_DRAG_THRESHOLD 20

View File

@ -65,33 +65,6 @@ private:
QBoxLayout *m_mainLayout;
};
class FixedPluginController : public AbstractPluginsController
{
Q_OBJECT
public:
explicit FixedPluginController(QObject *parent);
void startLoader();
Q_SIGNALS:
void pluginItemInserted(StretchPluginsItem *);
void pluginItemRemoved(StretchPluginsItem *);
void pluginItemUpdated(StretchPluginsItem *);
protected:
void itemAdded(PluginsItemInterface * const itemInter, const QString &itemKey) override;
void itemUpdate(PluginsItemInterface * const itemInter, const QString &) override;
void itemRemoved(PluginsItemInterface * const itemInter, const QString &) override;
bool needLoad(PluginsItemInterface *itemInter) override;
void requestWindowAutoHide(PluginsItemInterface * const, const QString &, const bool) override {}
void requestRefreshWindowVisible(PluginsItemInterface * const, const QString &) override {}
void requestSetAppletVisible(PluginsItemInterface * const, const QString &, const bool) override {}
private:
QList<StretchPluginsItem *> m_pluginItems;
};
class StretchPluginsItem : public DockItem
{
Q_OBJECT