Skip to content

Commit d61fcee

Browse files
committed
refactor: optimize plugin loading and QML registration
This refactor improves plugin management by separating QML registration from plugin object creation. Key changes include: 1. Added QML_ENGINE_PROPERTY constant for QML engine property name 2. Modified DCC_FACTORY_CLASS macro to accept variadic arguments for QML registration 3. Added dccObject() method in factory to handle QML type registration on main thread 4. Created containsByName() method for more efficient module filtering 5. Improved plugin loading sequence with proper thread management 6. Moved all QML registration calls from constructors to factory's dccObject() method 7. Removed unnecessary QML integration headers from model classes The changes ensure QML type registration happens on the main thread while plugin objects are created in worker threads, preventing threading issues and improving performance. Log: Optimized plugin loading process and QML registration Influence: 1. Test plugin loading and module display in control center 2. Verify all QML components are properly registered and accessible 3. Check module hiding functionality with wildcard patterns 4. Test thread safety during plugin initialization 5. Verify no regression in existing functionality refactor: 优化插件加载和 QML 注册流程 本次重构改进了插件管理机制,将 QML 注册与插件对象创建分离。主要变更 包括: 1. 添加 QML_ENGINE_PROPERTY 常量用于 QML 引擎属性名 2. 修改 DCC_FACTORY_CLASS 宏支持可变参数用于 QML 注册 3. 在工厂类中添加 dccObject() 方法处理主线程中的 QML 类型注册 4. 创建 containsByName() 方法实现更高效的模块过滤 5. 改进插件加载序列,优化线程管理 6. 将所有 QML 注册调用从构造函数移至工厂的 dccObject() 方法 7. 从模型类中移除不必要的 QML 集成头文件 这些变更确保 QML 类型注册在主线程执行,而插件对象在工作线程创建,避免线 程问题并提升性能。 Log: 优化插件加载过程和 QML 注册机制 Influence: 1. 测试控制中心插件加载和模块显示 2. 验证所有 QML 组件正确注册并可访问 3. 检查通配符模式下的模块隐藏功能 4. 测试插件初始化期间的线程安全性 5. 验证现有功能无回归 PMS: BUG-309197
1 parent 39e7ec7 commit d61fcee

26 files changed

Lines changed: 117 additions & 123 deletions

File tree

include/dccfactory.h

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2024 - 2027 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
// SPDX-License-Identifier: GPL-3.0-or-later
44
#ifndef DCCFACTORY_H
@@ -8,6 +8,7 @@
88

99
namespace dccV25 {
1010
#define DccFactory_iid "org.deepin.dde.dcc-factory/v1.0"
11+
#define QML_ENGINE_PROPERTY "QmlEngin"
1112
class DccObject;
1213

1314
class DccFactory : public QObject
@@ -16,28 +17,36 @@ class DccFactory : public QObject
1617
public:
1718
using QObject::QObject;
1819

19-
// 作为数据返回,会导出为dccData供main.qml使用
20+
// 作为数据返回,会导出为dccData供main.qml使用(在子线程执行)
2021
virtual QObject *create(QObject * = nullptr) { return nullptr; }
2122

22-
// 未提供qml的,可在此自己加载qml返回DccObject对象
23-
virtual DccObject *dccObject(QObject * = nullptr) { return nullptr; }
23+
// 未提供qml的,可在此自己加载qml返回DccObject对象,qml相关操作,如注册qml类型(在主线程中执行)
24+
virtual QObject *dccObject(QObject * = nullptr) { return nullptr; }
2425
};
2526
} // namespace dccV25
2627
Q_DECLARE_INTERFACE(dccV25::DccFactory, DccFactory_iid)
2728

28-
#define DCC_FACTORY_CLASS(classname) \
29-
namespace { \
30-
class Q_DECL_EXPORT classname##DccFactory : public dccV25::DccFactory \
31-
{ \
32-
Q_OBJECT \
33-
Q_PLUGIN_METADATA(IID DccFactory_iid) \
34-
Q_INTERFACES(dccV25::DccFactory) \
35-
public: \
36-
using dccV25::DccFactory::DccFactory; \
37-
QObject *create(QObject *parent = nullptr) override \
38-
{ \
39-
return new classname(parent); \
40-
} \
41-
}; \
29+
#define DCC_FACTORY_CLASS(classname, ...) \
30+
namespace { \
31+
class classname##DccFactory : public dccV25::DccFactory \
32+
{ \
33+
Q_OBJECT \
34+
Q_PLUGIN_METADATA(IID DccFactory_iid) \
35+
Q_INTERFACES(dccV25::DccFactory) \
36+
public: \
37+
using dccV25::DccFactory::DccFactory; \
38+
QObject *create(QObject *parent = nullptr) override \
39+
{ \
40+
return new classname(parent); \
41+
} \
42+
QObject *dccObject(QObject * = nullptr) override \
43+
{ \
44+
auto executeQmlRegisters = []() { \
45+
__VA_ARGS__; \
46+
}; \
47+
executeQmlRegisters(); \
48+
return nullptr; \
49+
} \
50+
}; \
4251
}
4352
#endif // DCCFACTORY_H

src/dde-control-center/dccmanager.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -468,22 +468,27 @@ void DccManager::initConfig()
468468
connect(m_dconfig, &DConfig::valueChanged, this, &DccManager::updateModuleConfig);
469469
}
470470

471-
bool DccManager::contains(const QSet<QString> &urls, const DccObject *obj)
471+
bool DccManager::containsByName(const QSet<QString> &urls, const QString &name)
472472
{
473473
for (auto &&url : urls) {
474474
if (url.contains("*")) {
475-
if (isMatch(url, obj)) {
475+
if (isMatchByName(url, name)) {
476476
return true;
477477
}
478478
} else {
479-
if (isEqual(url, obj)) {
479+
if (isEqualByName(url, name)) {
480480
return true;
481481
}
482482
}
483483
}
484484
return false;
485485
}
486486

487+
bool DccManager::contains(const QSet<QString> &urls, const DccObject *obj)
488+
{
489+
return containsByName(urls, obj->parentName() + "/" + obj->name());
490+
}
491+
487492
QStringList DccManager::splitUrl(const QString &url, QString &targetName)
488493
{
489494
QStringList paths = url.split("/", Qt::SkipEmptyParts);

src/dde-control-center/dccmanager.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ class DccManager : public DccApp, protected QDBusContext
5959

6060
inline const QSet<QString> &hideModule() const { return m_hideModule; }
6161

62+
static bool isMatchByName(const QString &url, const QString &name);
63+
static bool isMatch(const QString &url, const DccObject *obj);
64+
static bool isEqualByName(const QString &url, const QString &name);
65+
static bool isEqual(const QString &url, const DccObject *obj);
66+
static bool containsByName(const QSet<QString> &urls, const QString &name);
67+
static bool contains(const QSet<QString> &urls, const DccObject *obj);
68+
6269
public Q_SLOTS:
6370
DccObject *object(const QString &name) override;
6471
void addObject(DccObject *obj) override;
@@ -89,12 +96,7 @@ public Q_SLOTS:
8996

9097
private:
9198
void initConfig();
92-
bool contains(const QSet<QString> &urls, const DccObject *obj);
9399
QStringList splitUrl(const QString &url, QString &targetName);
94-
bool isMatchByName(const QString &url, const QString &name);
95-
bool isMatch(const QString &url, const DccObject *obj);
96-
bool isEqualByName(const QString &url, const QString &name);
97-
bool isEqual(const QString &url, const DccObject *obj);
98100
DccObject *findObject(const QString &url);
99101
QVector<DccObject *> findObjects(const QString &url, bool one = false);
100102
const DccObject *findParent(const DccObject *obj);

src/dde-control-center/pluginmanager.cpp

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ struct PluginData
8080
DccObject *mainObj;
8181
DccObject *soObj;
8282
QObject *data;
83+
DccFactory *factory;
8384
QThread *thread;
8485
uint status;
8586

@@ -91,6 +92,7 @@ struct PluginData
9192
, mainObj(nullptr)
9293
, soObj(nullptr)
9394
, data(nullptr)
95+
, factory(nullptr)
9496
, thread(nullptr)
9597
, status(PluginBegin)
9698
{
@@ -133,7 +135,6 @@ void LoadPluginTask::doLoadSo()
133135
QElapsedTimer timer;
134136
timer.start();
135137
QObject *dataObj = nullptr;
136-
DccObject *soObj = nullptr;
137138
if (QFile::exists(soPath)) {
138139
if (m_pManager->isDeleting()) {
139140
return;
@@ -169,10 +170,7 @@ void LoadPluginTask::doLoadSo()
169170
if (dataObj && dataObj->parent()) {
170171
dataObj->setParent(nullptr);
171172
}
172-
soObj = factory->dccObject();
173-
if (soObj && soObj->parent()) {
174-
soObj->setParent(nullptr);
175-
}
173+
m_data->factory = factory;
176174
} while (false);
177175
}
178176
} else {
@@ -181,16 +179,11 @@ void LoadPluginTask::doLoadSo()
181179
if (dataObj) {
182180
m_data->data = dataObj;
183181
}
184-
if (soObj) {
185-
m_data->soObj = soObj;
186-
}
187182
if (m_data->data) {
188183
m_data->data->moveToThread(m_pManager->thread());
189-
m_data->data->setParent(m_pManager->parent());
190184
}
191-
if (m_data->soObj) {
192-
m_data->soObj->moveToThread(m_pManager->thread());
193-
m_data->soObj->setParent(m_pManager->parent());
185+
if (m_data->factory) {
186+
m_data->factory->moveToThread(m_pManager->thread());
194187
}
195188
Q_EMIT m_pManager->updatePluginStatus(m_data, DataEnd, ": load plugin finished. elapsed time :" + QString::number(timer.elapsed()));
196189
}
@@ -327,6 +320,20 @@ void PluginManager::loadPlugin(PluginData *plugin)
327320
addMainObject(plugin);
328321
Q_EMIT updatePluginStatus(plugin, PluginEnd, QString());
329322
} else if ((plugin->status & (DataEnd | MainObjLoad)) == DataEnd) {
323+
if (plugin->data) {
324+
plugin->data->setParent(this);
325+
QJSEngine::setObjectOwnership(plugin->data, QQmlEngine::CppOwnership);
326+
}
327+
if (plugin->factory) {
328+
plugin->factory->setProperty(QML_ENGINE_PROPERTY, QVariant::fromValue(m_manager->engine()));
329+
QObject *obj = plugin->factory->dccObject();
330+
DccObject *soObj = dynamic_cast<DccObject *>(obj);
331+
if (soObj) {
332+
plugin->soObj = soObj;
333+
} else if (obj) {
334+
obj->deleteLater();
335+
}
336+
}
330337
loadMain(plugin);
331338
} else if ((plugin->status & (ModuleEnd | DataBegin)) == ModuleEnd) {
332339
if (plugin->module) {
@@ -371,7 +378,7 @@ void PluginManager::loadMetaData(PluginData *plugin)
371378
return;
372379
}
373380
updatePluginType(plugin);
374-
if (m_manager->hideModule().contains(plugin->name)) {
381+
if (DccManager::containsByName(m_manager->hideModule(), plugin->name)) {
375382
// 跳过隐藏的模块,需要动态加载回来
376383
Q_EMIT updatePluginStatus(plugin, PluginEnd | MetaDataEnd, QString());
377384
return;
@@ -498,9 +505,11 @@ void PluginManager::createMain(QQmlComponent *component)
498505
QObject *object = component->create(context);
499506
component->deleteLater();
500507
if (!object) {
508+
context->deleteLater();
501509
Q_EMIT updatePluginStatus(plugin, MainObjErr | MainObjEnd, " component create main object is null:" + component->errorString());
502510
return;
503511
}
512+
context->setParent(object);
504513
object->setParent(plugin->module ? plugin->module : m_rootModule);
505514
plugin->mainObj = qobject_cast<DccObject *>(object);
506515
Q_EMIT updatePluginStatus(plugin, MainObjEnd, ": create main finished");

src/plugin-accounts/operation/accountscontroller.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
// SPDX-License-Identifier: GPL-3.0-or-later
44

@@ -19,6 +19,7 @@
1919
#include <QPainterPath>
2020
#include <QBuffer>
2121
#include <QTimer>
22+
#include <QtQml/qqml.h>
2223

2324
#include <DSysInfo>
2425

@@ -30,7 +31,7 @@
3031
DCORE_USE_NAMESPACE
3132
namespace dccV25 {
3233

33-
DCC_FACTORY_CLASS(AccountsController)
34+
DCC_FACTORY_CLASS(AccountsController, qmlRegisterType<CreationResult>("AccountsController", 1, 0, "CreationResult"))
3435

3536
static bool isUserGroupName(int gid, const QString &name)
3637
{
@@ -45,8 +46,6 @@ static bool isUserGroupName(int gid, const QString &name)
4546
AccountsController::AccountsController(QObject *parent)
4647
: QObject{ parent }
4748
{
48-
qmlRegisterType<CreationResult>("AccountsController", 1, 0, "CreationResult");
49-
5049
m_model = new UserModel(this);
5150
m_worker = new AccountsWorker(m_model, this);
5251

src/plugin-accounts/operation/accountscontroller.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
// SPDX-License-Identifier: GPL-3.0-or-later
44

@@ -12,7 +12,6 @@
1212
#include <QObject>
1313
#include <QSortFilterProxyModel>
1414
#include <QHash>
15-
#include <QtQml/qqml.h>
1615

1716
namespace dccV25 {
1817

src/plugin-authentication/operation/biometricauthcontroller.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
1+
//SPDX-FileCopyrightText: 2025 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
//SPDX-License-Identifier: GPL-3.0-or-later
44

@@ -8,19 +8,17 @@
88

99
namespace dccV25 {
1010

11-
DCC_FACTORY_CLASS(BiometricAuthController)
11+
DCC_FACTORY_CLASS(BiometricAuthController, \
12+
qmlRegisterType<CharaMangerModel>("org.deepin.dcc.account.biometric", 1, 0, "CharaMangerModel"); \
13+
qmlRegisterType<FaceAuthController>("org.deepin.dcc.account.biometric", 1, 0, "FaceAuthController"); \
14+
qmlRegisterType<FingerprintAuthController>("org.deepin.dcc.account.biometric", 1, 0, "FingerprintAuthController"); \
15+
qmlRegisterType<IrisAuthController>("org.deepin.dcc.account.biometric", 1, 0, "IrisAuthController"))
1216

1317
BiometricAuthController::BiometricAuthController(QObject *parent)
1418
: QObject(parent)
1519
, m_charaModel(new CharaMangerModel(this))
1620
, m_charaWorker(new CharaMangerWorker(m_charaModel, this))
1721
{
18-
// 注册QML类型
19-
qmlRegisterType<CharaMangerModel>("org.deepin.dcc.account.biometric", 1, 0, "CharaMangerModel");
20-
qmlRegisterType<FaceAuthController>("org.deepin.dcc.account.biometric", 1, 0, "FaceAuthController");
21-
qmlRegisterType<FingerprintAuthController>("org.deepin.dcc.account.biometric", 1, 0, "FingerprintAuthController");
22-
qmlRegisterType<IrisAuthController>("org.deepin.dcc.account.biometric", 1, 0, "IrisAuthController");
23-
2422
// 创建子控制器
2523
m_faceController = new FaceAuthController(m_charaModel, m_charaWorker, this);
2624
m_fingerprintController = new FingerprintAuthController(m_charaModel, m_charaWorker, this);

src/plugin-bluetooth/operation/bluetoothinteraction.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
// SPDX-License-Identifier: GPL-3.0-or-later
44

@@ -13,9 +13,6 @@ BluetoothInteraction::BluetoothInteraction(QObject *parent)
1313
, m_work(new BluetoothWorker(m_model, this))
1414
{
1515
m_work->activate();
16-
17-
qmlRegisterType<BluetoothWorker>("dcc", 1, 0, "BluetoothWorker");
18-
qmlRegisterType<BluetoothModel>("dcc", 1, 0, "BluetoothModel");
1916
}
2017

2118
BluetoothModel *BluetoothInteraction::model() const
@@ -39,6 +36,8 @@ void BluetoothInteraction::setWork(BluetoothWorker *newWork)
3936
}
4037

4138

42-
DCC_FACTORY_CLASS(BluetoothInteraction)
39+
DCC_FACTORY_CLASS(BluetoothInteraction, \
40+
qmlRegisterType<BluetoothWorker>("dcc", 1, 0, "BluetoothWorker"); \
41+
qmlRegisterType<BluetoothModel>("dcc", 1, 0, "BluetoothModel"))
4342

4443
#include "bluetoothinteraction.moc"

src/plugin-bluetooth/operation/bluetoothmodel.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
//SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
1+
//SPDX-FileCopyrightText: 2018 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
//SPDX-License-Identifier: GPL-3.0-or-later
44
#ifndef DCC_BLUETOOTH_BLUETOOTHMODEL_H
55
#define DCC_BLUETOOTH_BLUETOOTHMODEL_H
66

77
#include <QObject>
8-
#include <QtQmlIntegration/qqmlintegration.h>
98

109
#include "bluetoothadapter.h"
1110
#include "bluetoothadaptersmodel.h"
@@ -18,8 +17,6 @@ class BluetoothModel : public QObject
1817
Q_PROPERTY(bool airplaneEnable READ airplaneEnable NOTIFY airplaneEnableChanged FINAL)
1918
Q_PROPERTY(bool showBluetooth READ showBluetooth NOTIFY showBluetoothChanged FINAL)
2019

21-
QML_NAMED_ELEMENT(BluetoothModel)
22-
QML_SINGLETON
2320
public:
2421
explicit BluetoothModel(QObject *parent = nullptr);
2522

src/plugin-commoninfo/operation/commoninfointeraction.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
1+
//SPDX-FileCopyrightText: 2018 - 2026 UnionTech Software Technology Co., Ltd.
22
//
33
//SPDX-License-Identifier: GPL-3.0-or-later
44

@@ -12,9 +12,6 @@ CommonInfoInteraction::CommonInfoInteraction(QObject *parent)
1212
, m_work(NULL)
1313
, m_mode(NULL)
1414
{
15-
qmlRegisterType<CommonInfoWork>("org.deepin.dcc.systemInfo", 1, 0, "CommonInfoWork");
16-
qmlRegisterType<CommonInfoModel>("org.deepin.dcc.systemInfo", 1, 0, "CommonInfoModel");
17-
1815
m_mode = new CommonInfoModel(this);
1916
m_work = new CommonInfoWork(m_mode, this);
2017

@@ -41,7 +38,9 @@ void CommonInfoInteraction::setMode(CommonInfoModel *newMode)
4138
m_mode = newMode;
4239
}
4340

44-
DCC_FACTORY_CLASS(CommonInfoInteraction)
41+
DCC_FACTORY_CLASS(CommonInfoInteraction,\
42+
qmlRegisterType<CommonInfoWork>("org.deepin.dcc.systemInfo", 1, 0, "CommonInfoWork"),\
43+
qmlRegisterType<CommonInfoModel>("org.deepin.dcc.systemInfo", 1, 0, "CommonInfoModel"))
4544

4645

4746
#include "commoninfointeraction.moc"

0 commit comments

Comments
 (0)