-
Notifications
You must be signed in to change notification settings - Fork 101
feat: dplugin #262
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: dplugin #262
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| #include "dplugin.h" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| // SPDX-FileCopyrightText: 2017 - 2023 UnionTech Software Technology Co., Ltd. | ||
| // | ||
| // SPDX-License-Identifier: LGPL-3.0-or-later | ||
|
|
||
| #ifndef DPLUGIN_H | ||
| #define DPLUGIN_H | ||
|
|
||
| #include "dtkcore_global.h" | ||
|
|
||
| #include <QLibrary> | ||
|
|
||
| #include <memory> | ||
|
|
||
| DCORE_BEGIN_NAMESPACE | ||
|
|
||
| class DPluginPrivate; | ||
|
|
||
| class DPlugin : public QObject | ||
| { | ||
| Q_OBJECT; | ||
|
|
||
| public: | ||
| static QList<std::shared_ptr<DPlugin>> listPlugins(const QStringList &extraLocations = {}); | ||
|
|
||
| const QScopedPointer<QLibrary> library; | ||
| QString name(); | ||
|
|
||
| private: | ||
| DPlugin(const QString &name, const QString &filename, const QString &version, QObject *parent = nullptr); | ||
|
|
||
| QScopedPointer<DPluginPrivate> d_ptr; | ||
| Q_DECLARE_PRIVATE(DPlugin); | ||
| }; | ||
|
|
||
| DCORE_END_NAMESPACE | ||
|
|
||
| #endif | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,129 @@ | ||||||
| // SPDX-FileCopyrightText: 2019 - 2023 UnionTech Software Technology Co., Ltd. | ||||||
| // | ||||||
| // SPDX-License-Identifier: LGPL-3.0-or-later | ||||||
|
|
||||||
| #include "dplugin.h" | ||||||
| #include "dplugin_p.h" | ||||||
|
|
||||||
| #include <QStandardPaths> | ||||||
| #include <QDebug> | ||||||
| #include <QDir> | ||||||
| #include <QJsonDocument> | ||||||
| #include <QJsonObject> | ||||||
|
|
||||||
| DCORE_BEGIN_NAMESPACE | ||||||
|
|
||||||
| QList<std::shared_ptr<DPlugin>> DPlugin::listPlugins(const QStringList &extraDirs) | ||||||
| { | ||||||
| auto pluginDirs = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation); | ||||||
|
|
||||||
| for (auto &pluginDir : pluginDirs) { | ||||||
| pluginDir = QStringList{pluginDir, "plugins"}.join(QDir::separator()); | ||||||
| } | ||||||
|
|
||||||
| pluginDirs.append(extraDirs); | ||||||
|
|
||||||
| qDebug() << "Searching dplugins in" << pluginDirs; | ||||||
|
|
||||||
| QList<std::shared_ptr<DPlugin>> plugins{}; | ||||||
|
|
||||||
| for (const auto &pluginDir : pluginDirs) { | ||||||
| plugins << DPluginPrivate::searchPluginsInPath(pluginDir); | ||||||
| } | ||||||
|
|
||||||
| return plugins; | ||||||
| } | ||||||
|
|
||||||
| QList<std::shared_ptr<DPlugin>> DPluginPrivate::searchPluginsInPath(const QString &pluginDirPath) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| { | ||||||
| auto const pluginDir = QDir(pluginDirPath); | ||||||
| auto const entryList = pluginDir.entryList(); | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 可以通过 |
||||||
|
|
||||||
| QList<std::shared_ptr<DPlugin>> result{}; | ||||||
|
|
||||||
| for (auto const &entry : entryList) { | ||||||
| auto filePath = QStringList{pluginDirPath, entry}.join(QDir::separator()); | ||||||
| auto fileInfo = QFileInfo(filePath); | ||||||
|
|
||||||
| // NOTE(black_desk): we do not load a large file (>4KB) into memory | ||||||
| if (!fileInfo.isFile() || fileInfo.size() > (1 << 11)) { | ||||||
| continue; | ||||||
| } | ||||||
|
|
||||||
| QFile file(filePath); | ||||||
| file.open(QIODevice::ReadOnly); | ||||||
| auto content = file.readAll(); | ||||||
|
|
||||||
| auto plugin = DPluginPrivate::pluginFromJsonContent(content); | ||||||
| if (!plugin) { | ||||||
| qWarning() << "Ignore invalid plugin config:" << filePath; | ||||||
| continue; | ||||||
| } | ||||||
| result << plugin; | ||||||
| } | ||||||
|
|
||||||
| return result; | ||||||
| } | ||||||
|
|
||||||
| std::shared_ptr<DPlugin> DPluginPrivate::pluginFromJsonContent(const QByteArray &content) | ||||||
| { | ||||||
| QJsonParseError err; | ||||||
| auto jsonDoc = QJsonDocument::fromJson(content, &err); | ||||||
| if (err.error || !jsonDoc.isObject()) { | ||||||
| return nullptr; | ||||||
| } | ||||||
|
|
||||||
| auto config = jsonDoc.object(); | ||||||
| if (!DPluginPrivate::configCompatible(config["pluginConfigVersion"])) { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||
| return nullptr; | ||||||
| } | ||||||
|
|
||||||
| auto nameVar = config["pluginName"]; | ||||||
| if (!nameVar.isString()) { | ||||||
| return nullptr; | ||||||
| } | ||||||
|
|
||||||
| auto name = nameVar.toString(); | ||||||
|
|
||||||
| auto versionVar = config["pluginVersion"]; | ||||||
| if (!nameVar.isString()) { | ||||||
| return nullptr; | ||||||
| } | ||||||
|
|
||||||
| auto version = versionVar.toString(); | ||||||
|
|
||||||
| auto filenameVar = config["pluginFilename"]; | ||||||
| if (!filenameVar.isString()) { | ||||||
| return nullptr; | ||||||
| } | ||||||
|
|
||||||
| auto filename = filenameVar.toString(); | ||||||
|
|
||||||
| return std::shared_ptr<DPlugin>(new DPlugin(name, filename, version)); | ||||||
| } | ||||||
|
|
||||||
| DPlugin::DPlugin(const QString &name, const QString &filename, const QString &version, QObject *parent) | ||||||
| : QObject(parent) | ||||||
| , library(new QLibrary(filename, version)) | ||||||
| , d_ptr(new DPluginPrivate(name, this)) | ||||||
| { | ||||||
| } | ||||||
|
|
||||||
| QString DPlugin::name() | ||||||
| { | ||||||
| Q_D(DPlugin); | ||||||
| return d->name; | ||||||
| } | ||||||
|
|
||||||
| bool DPluginPrivate::configCompatible(const QJsonValueRef &version) | ||||||
| { | ||||||
| return version.isString() && version.toString() == "1"; | ||||||
| } | ||||||
|
|
||||||
| DPluginPrivate::DPluginPrivate(const QString &name, DPlugin *parent) | ||||||
| : QObject(parent) | ||||||
| , name(name) | ||||||
| { | ||||||
| } | ||||||
|
|
||||||
| DCORE_END_NAMESPACE | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. | ||
| // | ||
| // SPDX-License-Identifier: LGPL-3.0-or-later | ||
|
|
||
| #ifndef DPLUGIN_P_H | ||
| #define DPLUGIN_P_H | ||
|
|
||
| #include "dplugin.h" | ||
|
|
||
| #include <QJsonValueRef> | ||
|
|
||
| DCORE_BEGIN_NAMESPACE | ||
|
|
||
| class DPlugin; | ||
|
|
||
| class DPluginPrivate : public QObject | ||
| { | ||
| Q_OBJECT; | ||
|
|
||
| public: | ||
| explicit DPluginPrivate(const QString &name, DPlugin *parent); | ||
| const QString name; | ||
|
|
||
| static QList<std::shared_ptr<DPlugin>> searchPluginsInPath(const QString &pluginDirPath); | ||
| static bool configCompatible(const QJsonValueRef &version); | ||
| static std::shared_ptr<DPlugin> pluginFromJsonContent(const QByteArray &content); | ||
|
|
||
| DPlugin *q_ptr; | ||
| Q_DECLARE_PUBLIC(DPlugin); | ||
| }; | ||
|
|
||
| DCORE_END_NAMESPACE | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,44 +1,28 @@ | ||
| set(UTILS_SOURCE | ||
| ${CMAKE_CURRENT_LIST_DIR}/dabstractunitformatter.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/ddbusextendedabstractinterface.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/ddbusextendedpendingcallwatcher.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/ddbusinterface.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/ddbussender.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/ddisksizeformatter.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dexportedinterface.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dnotifysender.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dpinyin.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dplugin.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/drecentmanager.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dtextencoding.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dthreadutils.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dtimedloop.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dtimeunitformatter.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dvtablehook.cpp | ||
| ) | ||
|
|
||
| if(LINUX) | ||
| set(UTILS_SOURCE | ||
| ${CMAKE_CURRENT_LIST_DIR}/dtimeunitformatter.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dabstractunitformatter.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/ddisksizeformatter.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/ddbussender.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/drecentmanager.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dnotifysender.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dpinyin.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dexportedinterface.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dvtablehook.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dthreadutils.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dtimedloop.cpp | ||
| set(UTILS_SOURCE ${UTILS_SOURCE} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I recommend using list(APPEND). |
||
| ${CMAKE_CURRENT_LIST_DIR}/dfileservices_linux.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dexportedinterface.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/ddbusinterface.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/ddbusextendedabstractinterface.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/ddbusextendedpendingcallwatcher.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dtextencoding.cpp | ||
| ) | ||
| else() | ||
| set(UTILS_SOURCE | ||
| ${CMAKE_CURRENT_LIST_DIR}/dtimeunitformatter.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dabstractunitformatter.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/ddisksizeformatter.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/ddbussender.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/drecentmanager.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dnotifysender.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dpinyin.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dexportedinterface.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dvtablehook.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dthreadutils.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dtimedloop.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dfileservices_dummy.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dexportedinterface.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/ddbusinterface.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/ddbusextendedabstractinterface.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/ddbusextendedpendingcallwatcher.cpp | ||
| ${CMAKE_CURRENT_LIST_DIR}/dtextencoding.cpp | ||
| ) | ||
| endif() | ||
|
|
||
| file(GLOB UTILS_HEADER | ||
| ${CMAKE_CURRENT_LIST_DIR}/../../include/util/* | ||
| ${CMAKE_CURRENT_LIST_DIR}/ddbusinterface_p.h | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should DPlugin derive from DObject? If yes, it's better to use D_DECLARE_PRIVATE. And remember to make DPluginPrivate derive from DObjectPrivate.